#!/bin/sh
######################################################################
#=====================================================================
#
#  applypatch
#
#  This script applies an ESRI Hot Fix/Patch/Service Pack to an existing 
#  product installation.
#
#  The following constants are required for this script.
#
#	AIVersion	:: identifies the version of ArcSDE being patched.
#	QFEVersion 	:: identifies the version of the QFE patch;
#			   should change with each QFE patch.
#	NameOfTOCFile   :: the TOC of files distributed on CD with 
#		     	   each patch (should never change)
#	NameOfTARFile   :: the compressed TAR patch file distributed on CD
#		     	   with each patch (should never change)
#
#=====================================================================
######################################################################

			###################
			#                 #
			# A Few Constants #
			#                 #
			###################

#ArcIMSFileTest="bin/aimsserver.exe"
ArcIMSFileTest="tools/uninstallArcIMS"
ArcInfoFileTest="bin/arc"
ArcSDEFileTest="bin/giomgr"
ArcSDEClientFolderTest="tools/client"
ArcSDKName="client"
ArcSDEServer="Server"
ArcSDEClient="Client"
Tru64Platform="tru64"
ApplyPatchTOC="applypatch.toc"
ApplyPatchTAR="patch_tar.z"
QFETestFile=""
QFETestFileBK=""
ArcServerFileTest=".Setup/uninstallArcGISServer"
ArcEngineRTFileTest="uninstallArcGISEngineRT"
ArcReaderFileTest="uninstallArcReader"
SPNumber=0

######################################################################
#=====================================================================
#
#  Function Synopsis:
#
#     Set_System_Commands	Set up location of system commands
#				based on platform this is being run
#     Get_Patch_Info		Get information from about the patch 
#				from the patch TOC file
#     MyDf			Determine available disk space in KB
#				(platform independant df)
#     MyDu			Determine size of a file in KB
#				(platform independant du)
#	my_pid()		determine PID of this process
#				(platform independant)
#     LenChr			Determine length of string -  
#				including trailing CR/LF
#     Error_Exit		The installation of the patch failed. 
#				This routine is called when none of 
#				the patch files have been installed 
#				yet and the product HOME is still in
# 				its original state
#=====================================================================
#     Size_Of_Patch		Determine disk space required by patch
#				files
#     Size_Of_Originals		Determine the total size of the files 
#				contained within the Updated TOC using
#				the size of the files already existing 
#				in the user's product install
#     Validate_Patch_Home	Validate PatchHome for location of 
#				patch files
#     Validate_Product_Path	Make sure that Product Home specified 
#				by the user is valid for installation
#     Validate_Save_Path	Make sure save path exists and is 
#				writeable
#	validate_superuser()    make sure user executing script is root (not
#				used at this time)
#     Update_TOC_File		Create an updated TOC file based on
#				what the user has installed in their
#				product HOME
#	Apply_The_Patch()	copies in the new files from compressed tar file
#	Validate_The_Patch()	validates that the patch files were installed.
#     Cut_String		Cuts the blanks from the end of the 
#				given string
#     Clean_Up			Delete any temporary files we might  
#				have created
#     List_Valid_Selections	Lists all valid/available options for 
#				ESRI Patch installation
#     Reiterate_Choice		Reiterates the choice the user made 
#				from valid selectable ESRI Patch 
#				installation options
#     Choose_Available_Install	Prompt user to select one of the 
#				available installations
#
#=====================================================================
######################################################################






######################################################################
#=====================================================================
#  Set_System_Commands()
#
#  Most commands that we use in this script are in /bin for most
#  platforms.  We assume that users will have /bin in their $path.
#
#  For commands that are NOT in /bin for some platforms, we specify 
#  the location over here because we cannot assume that the $path
#  variable will be able to find them.
#=====================================================================
######################################################################
Set_System_Commands() 
{

   #=============================================================
   #  Set default values.
   #=============================================================
   DF="/bin/df"
   TAR="/bin/tar"
   ZCAT="/bin/zcat"
   LS="/bin/ls"
   
   #XXXXX========================================================
   #  Set special case values (based upon platform).
   #=============================================================
   case `uname` in
      AIX)
         CurrentPlatform="ibm"
         CurrentPlatformUC="IBM"
         ;;
      HP-UX)
         IsHPIA=`uname -a | grep "ia64"`
         if [ "X$IsHPIA" != "X" ]
         then
            CurrentPlatform="hpia"
            CurrentPlatformUC="HPIA"
         else 
            CurrentPlatform="hp"
            CurrentPlatformUC="HP"
         fi
         ;;
      Linux)
         CurrentPlatform="linux"
         CurrentPlatformUC="Linux"
         ;;
      OSF1)
         CurrentPlatform="tru64"
         CurrentPlatformUC="Tru64"
         ;;
      SunOS)
         CurrentPlatform="solaris"
         CurrentPlatformUC="Solaris"
         DF="/usr/sbin/df"
         LS="/usr/bin/ls"
         TAR="/usr/sbin/tar"
         ;;
      IRIX*)
         CurrentPlatform="sgi"
         CurrentPlatformUC="SGI"
         DF="/usr/sbin/df"
         LS="/usr/bin/ls"
         ZCAT="/usr/bsd/zcat"
         TAR="/usr/bin/tar"
         ;;
   esac
   
}


######################################################################
#=====================================================================
#  Print_Applypatch_Intro()
#
#  
#=====================================================================
######################################################################
Print_Applypatch_Intro()
{

   echo ""
   echo "  ###################################################################"
   echo "  ==================================================================="
   echo ""
   echo "                     ESRI installation tool"
   echo ""
   echo "  ==================================================================="
   echo "  ###################################################################"
   echo ""
   echo "  At any prompt, press the Return key to take the default option"
   echo "  shown in parenthesis or press 'q' to quit the installation process."
   echo ""
   echo "  Since you are currently running this installation on $CurrentPlatformUC, you"
   echo "  will only be able to install $CurrentPlatformUC setups."
   echo ""

}


######################################################################
#=====================================================================
#  List_Valid_Selections()
#
#  
#=====================================================================
######################################################################
List_Valid_Selections()
{

   #=============================================================
   #  Initialize variables.
   #=============================================================
   ThePosition=0
   
   #XXXXX========================================================
   #  Get the process ID of the current process and create a
   #  temporary scratch file in the /tmp directory (based on the 
   #  PID).
   #=============================================================
   ProcessID=$$
   TempFile1=/tmp/applypatch.tmp1.$ProcessID
   
   #=============================================================
   #  Try to create an empty temporary file.  Print an error
   #  message, clean up and exit if it fails to create.
   #=============================================================
   cat /dev/null > $TempFile1
   if test $? -ne 0
   then
      echo ""
      echo ""
      echo "*** ERROR:"
      echo "  Creating scratch file $TempFile1."
      echo "  Make sure that at least 10K bytes are free in /tmp."
      echo ""
      echo "  Cleaning up and Exiting..."
      echo ""
      Clean_Up
      exit 1
   fi
   
   #=============================================================
   #  Print valid Product-Platform selection header.
   #=============================================================
   echo ""
   echo "  The Current Valid Product-Platform Installation(s)"
   echo "  ==================================================================="

   
   #=============================================================
   #  Walk through the list of all files and directories in the
   #  current directory.
   #=============================================================
   #=============================================================
   # Find all SDE Clients first.
   #=============================================================
   for Item in `$LS -1`
   do
      
      #==========================================================
      #  Proceed to list availabe items (if applicable) if the
      #  current item is a directory.
      #==========================================================
      if [ -d $Item ]
      then 
         
         #=======================================================
         #  Set the CurrentTOC variable to the current
         #  directories $ApplyPatchTOC file.
         #=======================================================
         CurrentTOC=$Item/$ApplyPatchTOC
         
         #=======================================================
         #  If the CurrentTOC exists, then we will use it to get
         #  the basic information for the current ESRI Patch 
         #  installation.
         #=======================================================
         if [ -f $CurrentTOC ]
         then
         
            #====================================================
            #  Get the current TOC file's QFE patch product.
            #====================================================
            TheProduct=`Get_Patch_Info Product $CurrentTOC`
            TheProduct=`Cut_String "$TheProduct"`
	                
            #XXXXX===============================================
            #  Determine if the current TOC file's patch product
            #  is ArcSDE.
            #====================================================
            IsArcSDE=0
            case $TheProduct in 
               [Aa][Rr][Cc][Ss][Dd][Ee])
                  IsArcSDE=1
                  ;;
               *)
            esac
            
            if [ $IsArcSDE = 1 ]
            then
               #====================================================
               #  If the CurrentPlatform corresponds to the platform
               #  given in the current directory...we proceed to 
               #  get information from the Current TOC file that
               #  we need to display to the user so they can make a
               #  selection.
               #====================================================
               Result1=`echo $Item | grep $CurrentPlatform`
               if [ "X$Result1" != "X" ]
               then
               
                  #=================================================
                  #  Get the product version, the product platform,
                  #  the QFE version and the QFE date.
                  #  Cut excess characters off the end of the 
                  #  information obtained.
                  #=================================================
                  TheVersion=`Get_Patch_Info Version $CurrentTOC`
                  TheVersion=`Cut_String "$TheVersion"`
                  TheServPack=`Get_Patch_Info ServicePack $CurrentTOC`
                  TheServPack=`Cut_String "$TheServPack"`
                  ThePlatform=`Get_Patch_Info Platform $CurrentTOC`
                  ThePlatform=`Cut_String "$ThePlatform"`
                  TheQFEVersion=`Get_Patch_Info QFEVersion $CurrentTOC`
                  TheQFEVersion=`Cut_String "$TheQFEVersion"`
                  TheQFEAbbreviated=`Get_Patch_Info QFEGeneral $CurrentTOC`
                  TheQFEAbbreviated=`Cut_String "$TheQFEAbbreviated"`
                  TheQFEDate=`Get_Patch_Info QFEDate $CurrentTOC`
                  TheQFEDate=`Cut_String "$TheQFEDate"`
                  TheBitSet=`Get_Patch_Info BitSet $CurrentTOC`
                  TheBitSet=`Cut_String "$TheBitSet"`
                  TheDataBase=`Get_Patch_Info DataBase $CurrentTOC`
                  TheDataBase=`Cut_String "$TheDataBase"`
  	          TheDataDB=`Get_Patch_Info DBInternal $CurrentTOC`
      	          TheDataDB=`Cut_String "$TheDataDB"`
      	       
      	          if [ $TheDataDB = $ArcSDKName ]
      	          then
               
                     #=================================================
                     #  Increment the position index.
                     #=================================================
                     ThePosition=`expr $ThePosition + 1`
               
                     #XXXXX============================================
                     #  Echo out the current SDE-SDK product information for
                     #  user selection.  What is displayed to the user
                     #  depends upon the product.
                     #=================================================
                     #XXXXX=========================================
                     #  If the current platform is Tru64, then do 
                     #  not print out the bitset - it's redundent.
                     #==============================================
                     if [ $CurrentPlatform = $Tru64Platform ]
                     then
                        #echo "  ($ThePosition)  $TheProduct $TheVersion $ArcSDEClient $TheQFEAbbreviated ($TheQFEVersion) on $ThePlatform ($TheQFEDate)"
                        echo "  ($ThePosition)  $TheQFEVersion $TheQFEAbbreviated for ($TheProduct $TheVersion $ArcSDEClient) on $ThePlatform ($TheQFEDate)"
                     else
                        #echo "  ($ThePosition)  $TheProduct $TheVersion $ArcSDEClient $TheQFEAbbreviated ($TheQFEVersion) on $ThePlatform($TheBitSet-bit) ($TheQFEDate)"
                        echo "  ($ThePosition)  $TheQFEVersion $TheQFEAbbreviated for ($TheProduct $TheVersion $ArcSDEClient) on $ThePlatform($TheBitSet-bit) ($TheQFEDate)"
                     fi

                     #=================================================
                     #  Echo out the current position and the Current
                     #  TOC file to a temporary file.  This will be 
                     #  used later when the user makes a selection.
                     #=================================================
                     echo "($ThePosition) $CurrentTOC" >> $TempFile1
         	  fi
               fi
            fi            
         fi
      fi
   done
   
   if [ $ThePosition != 0 ]
   then
      echo ""
   fi
   
   #=============================================================
   # Find all product info except ArcSDE Clients.
   #=============================================================
   for Item in `$LS -1`
   do
      
      #==========================================================
      #  Proceed to list availabe items (if applicable) if the
      #  current item is a directory.
      #==========================================================
      if [ -d $Item ]
      then 
         
         #=======================================================
         #  Set the CurrentTOC variable to the current
         #  directories $ApplyPatchTOC file.
         #=======================================================
         CurrentTOC=$Item/$ApplyPatchTOC
         
         #=======================================================
         #  If the CurrentTOC exists, then we will use it to get
         #  the basic information for the current ESRI Patch 
         #  installation.
         #=======================================================
         if [ -f $CurrentTOC ]
         then
         
            #====================================================
            #  Get the current TOC file's QFE patch product.
            #====================================================
            TheProduct=`Get_Patch_Info Product $CurrentTOC`
            TheProduct=`Cut_String "$TheProduct"`
            
            #XXXXX===============================================
            #  Determine if the current TOC file's patch product
            #  is ArcSDE.
            #====================================================
            IsArcSDE=0
            case $TheProduct in 
               [Aa][Rr][Cc][Ss][Dd][Ee])
                  IsArcSDE=1
                  ;;
               [Aa][Rr][Cc][Ii][Nn][Ff][Oo])
                  TheProduct="${TheProduct} Workstation"
                  ;;
               [Aa][Rr][Cc][Ss][Ee][Rr][Vv][Ee][Rr])
                  TheProduct="ArcGIS Server"
                  ;;
               [Aa][Rr][Cc][Ee][Nn][Gg][Ii][Nn][Ee])
                  TheProduct="ArcGIS Engine Runtime"
                  ;;
               [Aa][Rr][Cc][Rr][Ee][Aa][Dd][Ee][Rr])
                  TheProduct="ArcReader"
                  ;;
               *)
            esac

            #====================================================
            #  If the CurrentPlatform corresponds to the platform
            #  given in the current directory...we proceed to 
            #  get information from the Current TOC file that
            #  we need to display to the user so they can make a
            #  selection.
            #====================================================
            Result1=`echo $Item | grep $CurrentPlatform`
            if [ "X$Result1" != "X" ]
            then
               
               #=================================================
               #  Get the product version, the product platform,
               #  the QFE version and the QFE date.
               #  Cut excess characters off the end of the 
               #  information obtained.
               #=================================================
               TheVersion=`Get_Patch_Info Version $CurrentTOC`
               TheVersion=`Cut_String "$TheVersion"`
               TheServPack=`Get_Patch_Info ServicePack $CurrentTOC`
               TheServPack=`Cut_String "$TheServPack"`
               ThePreHotFix=`Get_Patch_Info PreHotFix $CurrentTOC`
               ThePreHotFix=`Cut_String "$ThePreHotFix"`
               ThePHFTitle=`Get_Patch_Info PHFTitle $CurrentTOC`
               ThePHFTitle=`Cut_String "$ThePHFTitle"`
               ThePlatform=`Get_Patch_Info Platform $CurrentTOC`
               ThePlatform=`Cut_String "$ThePlatform"`
               TheQFENumber=`Get_Patch_Info QFEID $CurrentTOC`
               TheQFENumber=`Cut_String "$TheQFENumber"`
               TheQFEVersion=`Get_Patch_Info QFEVersion $CurrentTOC`
               TheQFEVersion=`Cut_String "$TheQFEVersion"`
               TheQFEAbbreviated=`Get_Patch_Info QFEGeneral $CurrentTOC`
               TheQFEAbbreviated=`Cut_String "$TheQFEAbbreviated"`
               TheQFEDate=`Get_Patch_Info QFEDate $CurrentTOC`
               TheQFEDate=`Cut_String "$TheQFEDate"`
               
               #XXXXX============================================
               #  If the current product is ArcSDE, get the
               #  product bitset and the product database.
               #=================================================
               if [ $IsArcSDE = 1 ]
               then
                  TheBitSet=`Get_Patch_Info BitSet $CurrentTOC`
                  TheBitSet=`Cut_String "$TheBitSet"`
                  TheDataBase=`Get_Patch_Info DataBase $CurrentTOC`
                  TheDataBase=`Cut_String "$TheDataBase"`
      		  TheDataDB=`Get_Patch_Info DBInternal $CurrentTOC`
      		  TheDataDB=`Cut_String "$TheDataDB"`
               fi

               #XXXXX============================================
               #  Echo out the current product information for
               #  user selection.  What is displayed to the user
               #  depends upon the product.
               #=================================================
               if [ $IsArcSDE = 1 ]
               then
               
                  #==============================================
                  # List ArcSDE Server Product info.
                  #==============================================
                  if [ $TheDataDB != $ArcSDKName ]
                  then
                  
                     #=================================================
                     #  Increment the position index.
                     #=================================================
                     ThePosition=`expr $ThePosition + 1`
                     
                     #XXXXX=========================================
                     #  If the current platform is Tru64, then do 
                     #  not print out the bitset - it's redundent.
                     #==============================================
                     if [ $CurrentPlatform = $Tru64Platform ]
                     then
                        #echo "  ($ThePosition)  $TheProduct $TheVersion $ArcSDEServer $TheQFEAbbreviated ($TheQFEVersion) for $TheDataBase on $ThePlatform ($TheQFEDate)"
                        echo "  ($ThePosition)  $TheQFEVersion $TheQFEAbbreviated for ($TheProduct $TheVersion $ArcSDEServer for $TheDataBase) on $ThePlatform ($TheQFEDate)"
                     else
                        #echo "  ($ThePosition)  $TheProduct $TheVersion $ArcSDEServer $TheQFEAbbreviated ($TheQFEVersion) for $TheDataBase on $ThePlatform($TheBitSet-bit) ($TheQFEDate)"
                        echo "  ($ThePosition)  $TheQFEVersion $TheQFEAbbreviated for ($TheProduct $TheVersion $ArcSDEServer for $TheDataBase) on $ThePlatform($TheBitSet-bit) ($TheQFEDate)"
                     fi
                  
                     #=================================================
                     #  Echo out the current position and the Current
                     #  TOC file to a temporary file.  This will be 
                     #  used later when the user makes a selection.
                     #=================================================
                     echo "($ThePosition) $CurrentTOC" >> $TempFile1
                  fi
               else
                  #=================================================
                  #  Increment the position index.
                  #=================================================
                  ThePosition=`expr $ThePosition + 1`
                  #echo "  ($ThePosition)  $TheProduct $TheVersion $TheQFEAbbreviated ($TheQFEVersion) on $ThePlatform ($TheQFEDate)"
                  echo "  ($ThePosition)  $TheQFEVersion $TheQFEAbbreviated for ($TheProduct $TheVersion) on $ThePlatform ($TheQFEDate)"
                  
                  #=================================================
                  #  Echo out the current position and the Current
                  #  TOC file to a temporary file.  This will be 
                  #  used later when the user makes a selection.
                  #=================================================
                  echo "($ThePosition) $CurrentTOC" >> $TempFile1
               fi
            fi            
         fi
      fi
   done
   
   #=============================================================
   #  If ThePosition counter is 0, we didn't find any valid
   #  installable QFE patches.  Print a message to the user,
   #  clean up and exit.
   #=============================================================
   if [ $ThePosition = 0 ]
   then
      echo ""
      echo "***ERROR:"
      echo "  There are no valid ESRI setups available."
      echo "  Please verify:"
      echo ""
      echo "  1.  You are running on the same platform/OS for the QFE"
      echo "      setup being installed."
      echo "  2.  You have downloaded the appropriate ESRI setup."
      echo "  3.  The applyupdate installation script exists in the"
      echo "      same directory that the downloaded ESRI setup"
      echo "      directory exists."
      echo ""
      echo "  Cleaning up and exiting..."
      echo ""
      Clean_Up
      exit 1
   fi

   echo ""
         
}


######################################################################
#=====================================================================
#  Clean_Up() 
#
#  Delete any temporary files we might have created.
#=====================================================================
######################################################################
Clean_Up() 
{
   rm -f $TmpPatchFile
   rm -f $UpdatedTOCFile
   rm -f $TempFile1
   cd $CurrentWorkingDir > /dev/null 2>&1
}


######################################################################
#=====================================================================
#  Get_Patch_Info()
#
#  Get information from about the patch from the patch TOC file.
#=====================================================================
######################################################################
Get_Patch_Info()
{

   #XXXXX========================================================
   #  Get appropriate information about the selected patch from 
   #  its corresponding TOC file.
   #=============================================================
   case $1 in
      Product)
         cat $2 | awk '/^#PN#/{print $2}'
         ;;
      Version)
         cat $2 | awk '/^#PN#/{print $3, $4}'
         ;;
      ServicePack)
         cat $2 | awk '/^#PS#/{print $2, $3}'
         ;;
      PreHotFix)
         cat $2 | awk '/^#PH#/{print $2, $3}'
         ;;
      PHFTitle)
         cat $2 | awk '/^#HT#/{print $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16}'
         ;;
      QFEID)
         cat $2 | awk '/^#QI#/{print $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16}'
         ;;
      Platform)
         cat $2 | awk '/^#PL#/{print $2, $3, $4}'
         ;;
      QFEVersion)
         cat $2 | awk '/^#QV#/{print $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16}'
         ;;
      QFEGeneral)
         cat $2 | awk '/^#QG#/{print $2, $3, $4, $5}'
         ;;
      QFEDate)
         cat $2 | awk '/^#QD#/{print $2, $3, $4, $5}'
         ;;
      BitSet)
         cat $2 | awk '/^#BS#/{print $2}'
         ;;
      DataBase)
         cat $2 | awk '/^#DB#/{print $2, $3, $4}'
         ;;
      DBInternal)
         cat $2 | awk '/^#DI#/{print $2, $3}'
         ;;
      AllDataBases)
         cat $2 | awk '/^#AD#/{print $2, $3, $4, $5, $6, $7, $8, $9}'
         ;;
      PlatInternal)
         cat $2 | awk '/^#PI#/{print $2, $3}'
         ;;
   esac
   
}


######################################################################
#=====================================================================
#  Cut_String()
#
#  Cuts the blanks from the end of the given string.
#=====================================================================
######################################################################
Cut_String()
{
   length=`LenChr "$1"`
   echo $1 | cut -c1-$length
}


######################################################################
#=====================================================================
#  LenChr() 
#
#  Determine length of string - including trailing CR/LF.
#=====================================================================
######################################################################
LenChr() 
{
   echo $1 | wc -c | awk '{print $1}'
}


######################################################################
#=====================================================================
#  User_Selection_Process()
#
#=====================================================================
######################################################################
User_Selection_Process()
{

   #=============================================================
   #  Initialize valid choice indicator.
   #=============================================================
   ValidChoice=0
   
   #=============================================================
   #  While no valid choice has been selected, print out
   #  available QFE patch installation selections.
   #=============================================================
   while [ $ValidChoice = 0 ]
   do

      #XXXXX=====================================================
      #  Prompt the user to make a selection from those listed
      #  read user's selection.
      #==========================================================
      if test `uname` = "Linux"
      then
         echo -n "Please make a selection from the list above [q] (1): "
      else
         echo    "Please make a selection from the list above [q] (1): \c"
      fi
      read Choice

   
      #==========================================================
      #  Perform actions based upon user's choice.
      #==========================================================
      case "X$Choice" in
         X)   
            ValidChoice=1
            Choice=1
            Reiterate_Choice
            ;;
         X[1-9]|X[1-9][0-9])
            if [ $Choice -le $ThePosition  -a  $Choice -gt 0 ] 
            then
               ValidChoice=1
               Reiterate_Choice
            fi
            ;;
         Xq|XQ)
            Voluntary_Quit
            ;;
      esac
      
      
      #==========================================================
      #  If a valid choice was made, the choice will be 
      #  reiterated.  Prompt the user to verify that the 
      #  reiterated choice was the one intended.  If yes, then
      #  continue to set ValidChoice to 1 so we can exit the 
      #  loop.  Otherwise, set ValidChoice to 0 to repeat the
      #  loop.
      #==========================================================
      if [ $ValidChoice = 1 ]
      then
      
         #XXXXX==================================================
         #  Verify (with the user) that the selection they made
         #  (and just reiterated) is correct.
         #=======================================================
         echo ""
         if test `uname` = "Linux"
         then
           echo -n "Is this the correct selection? [y,n,q] (y): "
         else
           echo    "Is this the correct selection? [y,n,q] (y): \c"
         fi
         read NewChoice

         #=======================================================
         #  Perform actions based upon users choice.
         #=======================================================
         case "X$NewChoice" in
            X|Xy|XY)   
               ValidChoice=1
               ;;
            Xn|XN)
               ValidChoice=0
               ;;
            Xq|XQ)
               Voluntary_Quit
               ;;
         esac
      fi

   done
   
   
   #=============================================================
   #  Remove the temporary file containing all valid selections.
   #=============================================================
   rm -f $TempFile1

   
}


######################################################################
#=====================================================================
#  Reiterate_Choice()
#
#=====================================================================
######################################################################
Reiterate_Choice()
{

   #=============================================================
   #  Based upon the user's choice, determine the selected QFE
   #  patch TOC file.
   #=============================================================
   SelectedTOC=`cat $TempFile1 | grep "^($Choice)" | awk '{print $2}'`

   #=============================================================
   #  Verify that the SelectedTOC file exists.  If it doesn't,
   #  print an error message to the user, clean up and exit.
   #=============================================================
   if [ ! -f $CurrentWorkingDir/$SelectedTOC ]
   then
      echo ""
      echo "*** ERROR:"
      echo "  Unable to validate the selected option's TOC file existence."
      echo ""
      echo "  TOC file path:  $CurrentWorkingDir/$SelectedTOC"
      echo ""
      echo "  Cleaning up and exiting..."
      echo ""
      Clean_Up
      exit 1
   fi
   
   #=============================================================
   #  Get the Selected TOC file's QFE patch product.
   #=============================================================
   ProductName=`Get_Patch_Info Product $SelectedTOC`
   ProductName=`Cut_String "$ProductName"`

   ProductVersion=`Get_Patch_Info Version $SelectedTOC`
   ProductVersion=`Cut_String "$ProductVersion"`

   #XXXXX========================================================
   #  Set flag to determine product.  If unable to determine
   #  product, print error message, clean up and exit.
   #=============================================================
   case $ProductName in 
      [Aa][Rr][Cc][Ii][Mm][Ss])
         ArcIMS=1
         ProdHomeName="AIMSHOME"
         ProductHome=$AIMSHOME
         ProductDispName=$ProductName
         QFETestFile=".ESRI_IMS_PATCH_LOG"
         QFETestFileBK="bin/.ESRI_IMS_PATCH_LOG"
         ;;
      [Aa][Rr][Cc][Ii][Nn][Ff][Oo])
         ArcInfo=1
         ProdHomeName="ARCHOME"
         ProductHome=$ARCHOME
         ProductDispName="${ProductName} Workstation"
         QFETestFile=".ESRI_WS_PATCH_LOG"
         QFETestFileBK="lib/.ESRI_WS_PATCH_LOG"
         ;;
      [Aa][Rr][Cc][Ss][Dd][Ee])
         ArcSDE=1
         ProdHomeName="SDEHOME"
         ProductHome=$SDEHOME
         ProductDispName=$ProductName
         QFETestFile=".ESRI_SDE_PATCH_LOG"
         QFETestFileBK="lib/.ESRI_SDE_PATCH_LOG"
         ;;
      [Aa][Rr][Cc][Ss][Ee][Rr][Vv][Ee][Rr])
         ArcGIS=1
         if [ $ProductVersion = "9.0" -o $ProductVersion = "9.1" ]
         then
            ProdHomeName="Z_ArcGISServer_INSTALL_DIR"
            ProductHome="$Z_ArcGISServer_INSTALL_DIR"
         else
            ProdHomeName=""
            ProductHome=""
	 fi        
         ProductDispName="ArcGIS Server"
         QFETestFile=".ESRI_S_PATCH_LOG"
         QFETestFileBK="bin/.ESRI_S_PATCH_LOG"
         ProductFolderName="server"
         ;;
      [Aa][Rr][Cc][Ee][Nn][Gg][Ii][Nn][Ee])
         ArcGIS=1
         ProdHomeName="Z_ENGINE_HOME"
         ProductHome="$Z_ENGINE_HOME"
         ProductDispName="ArcGIS Engine Runtime"
         QFETestFile=".ESRI_E_PATCH_LOG"
         QFETestFileBK="bin/.ESRI_E_PATCH_LOG"
         ProductFolderName="engine"
         ;;
      [Aa][Rr][Cc][Rr][Ee][Aa][Dd][Ee][Rr])
         ArcGIS=1
         ProdHomeName="Z_ArcReader_INSTALL_DIR"
         ProductHome="$Z_ArcReader_INSTALL_DIR"
         ProductDispName="ArcReader"
         QFETestFile=".ESRI_R_PATCH_LOG"
         QFETestFileBK="bin/.ESRI_R_PATCH_LOG"
         ProductFolderName="arcreader"
         ;;
     *)
         echo ""
         echo ""
         echo "*** ERROR:"
         echo "  Unable to determine product from supplied TOC file."
         echo "  The ESRI Patch installation has failed."
         echo ""
         echo "  Cleaning up and Exiting..."
         echo ""
         Clean_Up
         exit 1
   esac

   #=============================================================
   #  Get appropriate QFE patch information from the Selected
   #  TOC.  Cut excess characters off of the end of the info
   #  obtained.
   #=============================================================
   ProductVersion=`Get_Patch_Info Version $SelectedTOC`
   ProductVersion=`Cut_String "$ProductVersion"`
   
   ProductSerPack=`Get_Patch_Info ServicePack $SelectedTOC`
   ProductSerPack=`Cut_String "$ProductSerPack"`
   
   ProductPreHotFix=`Get_Patch_Info PreHotFix $SelectedTOC`
   ProductPreHotFix=`Cut_String "$ProductPreHotFix"`
   ProductPHFTitle=`Get_Patch_Info PHFTitle $SelectedTOC`
   ProductPHFTitle=`Cut_String "$ProductPHFTitle"`
   
   ProductPlatform=`Get_Patch_Info Platform $SelectedTOC`
   ProductPlatform=`Cut_String "$ProductPlatform"`
   QFENumber=`Get_Patch_Info QFEID $SelectedTOC`
   QFENumber=`Cut_String "$QFENumber"`
   QFEVersion=`Get_Patch_Info QFEVersion $SelectedTOC`
   QFEVersion=`Cut_String "$QFEVersion"`
   QFEDate=`Get_Patch_Info QFEDate $SelectedTOC`
   QFEDate=`Cut_String "$QFEDate"`
   QFEAbbreviated=`Get_Patch_Info QFEGeneral $SelectedTOC`
   QFEAbbreviated=`Cut_String "$QFEAbbreviated"`

   ArcSDESet=""
   
   #XXXXX=======================================================
   #  If the current product is ArcSDE, get appropriate QFE patch
   #  information related to ArcSDE.  Cut excess characters off
   #  of the end of the info obtained.
   #=============================================================
   if [ $ArcSDE = 1 ]
   then
      ProductBitSet=`Get_Patch_Info BitSet $SelectedTOC`
      ProductBitSet=`Cut_String "$ProductBitSet"`
      CurrentDBFormal=`Get_Patch_Info DataBase $SelectedTOC`
      CurrentDBFormal=`Cut_String "$CurrentDBFormal"`
      CurrentDB=`Get_Patch_Info DBInternal $SelectedTOC`
      CurrentDB=`Cut_String "$CurrentDB"`
      if [ $CurrentDB = $ArcSDKName ]
      then 
         ArcSDESet=$ArcSDEClient
      else
         ArcSDESet=$ArcSDEServer
      fi
   fi

   #XXXXX=======================================================
   #  Reiterate the choice to the user for their verification.
   #=============================================================
   echo ""
   if [ $ArcSDE = 1 ] 
   then
      if [ $CurrentPlatform = $Tru64Platform ]
      then
         if [ $CurrentDB = $ArcSDKName ]
         then
            #echo "    $ProductDispName $ProductVersion $ArcSDEClient $QFEAbbreviated ($QFEVersion) on $ProductPlatform ($QFEDate)"
            echo "    $QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDEClient) on $ProductPlatform ($QFEDate)"
         else
            #echo "    $ProductDispName $ProductVersion $ArcSDEServer $QFEAbbreviated ($QFEVersion) for $CurrentDBFormal on $ProductPlatform ($QFEDate)"
            echo "    $QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDEServer for $CurrentDBFormal) on $ProductPlatform ($QFEDate)"
         fi
      else
         if [ $CurrentDB = $ArcSDKName ]
         then
            #echo "    $ProductDispName $ProductVersion $ArcSDEClient $QFEAbbreviated ($QFEVersion) on $ProductPlatform($ProductBitSet-bit) ($QFEDate)"
            echo "    $QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDEClient) on $ProductPlatform($ProductBitSet-bit) ($QFEDate)"
         else
            #echo "    $ProductDispName $ProductVersion $ArcSDEServer $QFEAbbreviated ($QFEVersion) for $CurrentDBFormal on $ProductPlatform($ProductBitSet-bit) ($QFEDate)"
            echo "    $QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDEServer for $CurrentDBFormal) on $ProductPlatform($ProductBitSet-bit) ($QFEDate)"
         fi
      fi
   else
      #echo "    $ProductDispName $ProductVersion $QFEAbbreviated ($QFEVersion) on $ProductPlatform ($QFEDate)"
      echo "    $QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion) on $ProductPlatform ($QFEDate)"
   fi
   
}


######################################################################
#=====================================================================
#  Voluntary_Quit()
#
#  If the user selects to quit, print out a message, clean up and 
#  exit.
#=====================================================================
######################################################################
Voluntary_Quit()
{
   echo ""
   echo "  YOU HAVE SELECTED TO QUIT PROCESSING."
   echo "  You will have to re-run applyupdate to install."
   echo "  Cleaning up and exiting..."
   echo ""
   Clean_Up
   exit 0
}


######################################################################
#=====================================================================
#  Validate_Patch_Home()
#
#  Validating PatchHome amounts to making sure we can find the patch
#  directory for $CurrentPlatform, and subsequently the TOC and TAR 
#  files.
#=====================================================================
######################################################################
Validate_Patch_Home() 
{

   #=============================================================
   #  First, make sure we have an absolute path-name to this 
   #  directory.  Some possible variations on the command line:
   #     .  applyupdate
   #     .  ./applyupdate
   #     .  dirname/applyupdate
   #     .  /drive/dirname/applyupdate
   #     .  ../dirname/applyupdate
   #=============================================================
   
   PatchHome=$CurrentWorkingDir
   #=============================================================
   	
   #XXXXX========================================================
   #  Second, test for patch directory.
   #=============================================================
   DirNotFound="no"   
   if [ $ArcSDE = 1 ]
   then
      if [ $ProductBitSet = "64" -a $CurrentPlatform != $Tru64Platform ]
      then
         TempPath="$PatchHome/$CurrentPlatform$ProductBitSet.$CurrentDB"
      else
         TempPath="$PatchHome/$CurrentPlatform.$CurrentDB"
      fi
   else 
      if [ $ArcGIS = 1 ]
      then
         TempPath="$PatchHome/$CurrentPlatform.$ProductFolderName"
      else
         TempPath="$PatchHome/$CurrentPlatform"
      fi
   fi
   
   if test ! -d "$TempPath"
   then
      DirNotFound="yes"      
   fi
      
   #=============================================================
   #  Now, look for files.
   #=============================================================
   FilesNotFound="no"
   if test ! -r "$TempPath/$ApplyPatchTOC" -o \
           ! -r "$TempPath/$ApplyPatchTAR"
   then
      FilesNotFound="yes"
   fi

   #=============================================================
   #  If the patch directory is not found OR the TOC and TAR
   #  files are not found, print an error message and set a
   #  return flag to indicate we need to exit processing.
   #=============================================================
   return_status=0
   if test "$DirNotFound" = "yes" -o "$FilesNotFound" = "yes"
   then
      echo ""
      echo ""
      echo "*** ERROR:"
      echo "  Unable to locate setup files:"
      echo ""
      echo "  $TempPath/$ApplyPatchTOC"
      echo "  $TempPath/$ApplyPatchTAR"
      echo ""
      return_status=1
   fi

   return $return_status
   
}


######################################################################
#=====================================================================
#  Error_Exit() 
#
#  The installation of the patch failed. This routine is called when 
#  none of the patch files have been installed yet and SDEHOME is 
#  still in its original state.
#=====================================================================
######################################################################
Error_Exit() 
{

  echo ""
  echo "*** ERROR:"
  echo "  The $QFEVersion installation has failed."
  echo ""
  echo "  Cleaning up and Exiting..."
  echo ""
  Clean_Up
  exit 1
  
}


######################################################################
#=====================================================================
#  Strip_Product_Version()
#
#  Strips the "."'s from the product version number.
#=====================================================================
######################################################################
Strip_Product_Version()
{

   #=============================================================
   #  Get the first four fields (separated by ".") if they exist.
   #=============================================================
   Field1=`echo $ProductVersion | cut -d. -f1`
   Field2=`echo $ProductVersion | cut -d. -f2`
   Field3=`echo $ProductVersion | cut -d. -f3`
   Field4=`echo $ProductVersion | cut -d. -f4`
   
   #=============================================================
   #  Set ProductVersionStripped to the four parsed fields.
   #=============================================================
   ProductVersionStripped="$Field1$Field2$Field3$Field4"
   if [ "$ProductVersionStripped" = "931" ]
   then
      ProductVersionStripped="93"
   fi
   
}


######################################################################
#=====================================================================
#  Pre_Install_Info()
#
#=====================================================================
######################################################################
Pre_Install_Info()
{
   
   #XXXXX=======================================================
   #  Generate header string containing selected product info.
   #=============================================================
   if [ $ArcSDE = 1 ] 
   then
      if [ $CurrentPlatform = $Tru64Platform ]
      then
         #TheHeader1="$ProductDispName $ProductVersion $ArcSDESet $QFEAbbreviated ($QFEVersion) for $CurrentDBFormal on $ProductPlatform Install"
         TheHeader1="$QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDESet for $CurrentDBFormal) on $ProductPlatform Install"
      else
         #TheHeader1="$ProductDispName $ProductVersion $ArcSDESet $QFEAbbreviated ($QFEVersion) for $CurrentDBFormal on $ProductPlatform($ProductBitSet-bit) Install"
         TheHeader1="$QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion $ArcSDESet for $CurrentDBFormal) on $ProductPlatform($ProductBitSet-bit) Install"
      fi
   else
      #TheHeader1="$ProductDispName $ProductVersion $QFEAbbreviated ($QFEVersion) on $ProductPlatform Install"
      TheHeader1="$QFEVersion $QFEAbbreviated for ($ProductDispName $ProductVersion) on $ProductPlatform Install"
   fi
   
   TheHeader2="($QFEDate)"
   
   
   echo ""
   echo ""
   echo "  ###################################################################"
   echo "  ==================================================================="
   echo ""
   echo "  $TheHeader1 $TheHeader2"
   echo ""
   echo "  ==================================================================="
   echo "  ###################################################################"
   echo ""
   if [ $ArcSDE = 1 ] 
   then
      if [ `LenChr "$ProductPreHotFix"` != 1 ]
      then
         echo "  You must have $ProductDispName $ProductVersion $ArcSDESet with $ProductPHFTitle installed before you can apply this $QFEAbbreviated."
      elif [ `LenChr "$ProductSerPack"` != 1 -a "$QFEAbbreviated" != "Service Pack" -a "$QFEAbbreviated" != "Update" ]
      then
         echo "  You must have $ProductDispName $ProductVersion $ArcSDESet Service Pack $ProductSerPack installed before you can apply this $QFEAbbreviated."
       else
         #echo "  You must have $ProductDispName $ProductVersion $ArcSDESet $ProductSerPack installed before you can apply this $QFEAbbreviated."
         echo "  You must have $ProductDispName $ProductVersion $ArcSDESet installed before you can apply this $QFEAbbreviated."
      fi
   else
      if [ `LenChr "$ProductPreHotFix"` != 1 ]
      then
         echo "  You must have $ProductDispName $ProductVersion with $ProductPHFTitle installed before you can apply this $QFEAbbreviated."
      elif [ `LenChr "$ProductSerPack"` != 1 -a "$QFEAbbreviated" != "Service Pack" -a "$QFEAbbreviated" != "Update" ]
      then
         echo "  You must have $ProductDispName $ProductVersion Service Pack $ProductSerPack installed before you can apply this $QFEAbbreviated."
      else
         echo "  You must have $ProductDispName $ProductVersion installed before you can apply this $QFEAbbreviated."
      fi
   fi
   echo ""
   if [ $ArcSDE = 1 ] 
   then
      echo "  You should install this $QFEAbbreviated when no one is using $ProductDispName $ProductVersion $ArcSDESet."
   else
      echo "  You should install this $QFEAbbreviated when no one is using $ProductDispName $ProductVersion."
   fi
   echo ""
   echo "  This $QFEAbbreviated is not compatible with other versions of $ProductDispName."
   echo ""
   echo ""
}


######################################################################
#=====================================================================
#  Set_Product_Home()
#
#  Determine the user's product HOME (or install location).  Will 
#  default to the current product HOME (if set) or let the user
#  override or define an install location.
#=====================================================================
######################################################################
Set_Product_Home()
{   
   
   #=============================================================
   #  Determine ProductHome...
   #=============================================================

   #=============================================================
   #  If $ProductHome is set, ask user if they want to use it as 
   #  the installation location for the QFE patch.  Otherwise,
   #  prompt for pathname to the Product installation location.
   #=============================================================
   test -n "$ProductHome"
   if [ $? = 0  -a $IsFirstTimeHomeSet = "yes" ]
   then

      echo ""
      echo "  Your $ProdHomeName variable is currently set to:"
      echo ""
      echo "     $ProductHome"
      echo ""
      echo "  If you would like to apply the $QFEAbbreviated to this version,"
      echo "  just press <return> to continue.  Otherwise, specify the path to"
      echo "  the installation you would like to update."
      echo ""

      #XXXXX=====================================================
      #  Prompt the user to enter an Installation path.
      #==========================================================
      if test `uname` = "Linux"
      then
         echo -n "Enter path [q] ($ProductHome): "
      else
         echo "Enter path [q] ($ProductHome): \c"
      fi
      read InstallPath
      
      
      #==========================================================
      #  Clean up and exit if the user selected to quit.
      #==========================================================
      if [ "X$InstallPath" = "Xq" -o "X$InstallPath" = "XQ" ];
      then
         Voluntary_Quit
      fi

      #==========================================================
      #  If user hits return (accepts default), assign the 
      #  ProductHome as the InstallPath.
      #==========================================================
      if [ "X$InstallPath" = "X" ];
      then
         InstallPath=$ProductHome
      fi
   
   #=============================================================
   #  If $ProductHome is not set, prompt user to enter a path for
   #  the product installation location for the QFE patch. 
   #  the installation location for the QFE patch. 
   #=============================================================
   else
      
      echo ""

      #XXXXX=====================================================
      #  Prompt the user to enter an Installation path.
      #==========================================================
      if test `uname` = "Linux"
      then
         echo -n "Enter path to your $ProductDispName $ProductVersion $ArcSDESet installation [q]: "
      else
         echo "Enter path to your $ProductDispName $ProductVersion $ArcSDESet installation [q]: \c"
      fi
      read InstallPath

      #==========================================================
      #  Clean up and exit if the user selected to quit.
      #==========================================================
      if [ "X$InstallPath" = "Xq" -o "X$InstallPath" = "XQ" ];
      then
         Voluntary_Quit
      fi

      #==========================================================
      #  Keep prompting user for an Installation path for as long
      #  as they do not enter one.
      #==========================================================
      while [ "X$InstallPath" = "X" ]
      do

         #XXXXX==================================================
         #  Prompt user for an Installation path.
         #=======================================================
         if test `uname` = "Linux"
         then
            echo -n "Enter path [q]: "
         else
            echo "Enter path [q]: \c"
         fi
         read InstallPath

         #=======================================================
         #  Clean up and exit if the user selected to quit.
         #=======================================================
         if [ "X$InstallPath" = "Xq" -o "X$InstallPath" = "XQ" ];
         then
            Voluntary_Quit
         fi

      done
   fi


   #=============================================================
   #  Validate the product installation path chosen by the user.
   #  If the path is invalid, keep asking until they enter a 
   #  valid path. 
   #=============================================================
   Validate_Product_Path
   while [ $? != 0 ]
   do
      echo ""

      #XXXXX=====================================================
      #  Prompt user for a valid Installation path.
      #==========================================================
      if test `uname` = "Linux"
      then
         echo -n "Enter path to your $ProductVersion installation [q]: "
      else
         echo "Enter path to your $ProductVersion installation [q]: \c"
      fi
      read InstallPath

      #==========================================================
      #  Clean up and exit if the user selected to quit.
      #==========================================================
      if [ "X$InstallPath" = "Xq" -o "X$InstallPath" = "XQ" ];
      then
         Voluntary_Quit
      fi

      #==========================================================
      #  Keep prompting user for an Installation path for as long
      #  as they do not enter one.
      #==========================================================
      while [ "X$InstallPath" = "X" ]
      do

         #XXXXX==================================================
         #  Prompt user for a valid Installation path.
         #=======================================================
         if test `uname` = "Linux"
         then
            echo -n "Enter path [q]: "
         else
            echo "Enter path [q]: \c"
         fi
         read InstallPath
         
         #=======================================================
         #  Clean up and exit if the user selected to quit.
         #=======================================================
         if [ "X$InstallPath" = "Xq" -o "X$InstallPath" = "XQ" ];
         then
            Voluntary_Quit
         fi
         
      done
      
      #==========================================================
      #  Validate the Installation path chosen by the user.
      #==========================================================
      Validate_Product_Path
      
   done
 
   echo ""

}


######################################################################
#=====================================================================
#  Validate_Product_Path()
#
#  Based upon the product and the product installation path given by
#  the user, verify this is a valid installation location.
#=====================================================================
######################################################################
Validate_Product_Path() 
{

   #XXXXX========================================================
   #  Test for valid ArcIMS installation location.
   #=============================================================
   if [ $ArcIMS = 1 ]
   then
      if test -f $InstallPath/$ArcIMSFileTest
      then
         Validate_PreServicePack
         if [ $? = 1 ]
         then
            return 1
         else
            return 0
         fi
      else
         echo ""
         #echo "***WARNING:  $InstallPath/$ArcIMSFileTest does not exist."
         echo "*** WARNING: "
         echo "  $InstallPath is not a valid $ProdHomeName location."
         echo "  Please try again."
         return 1
      fi
   fi
   
   #XXXXX========================================================
   #  Test for valid ArcInfo installation location.
   #=============================================================
   if [ $ArcInfo = 1 ]
   then
      if test -f $InstallPath/$ArcInfoFileTest
      then
         return 0
      else
         echo ""
         #echo "***WARNING:  $InstallPath/$ArcInfoFileTest does not exist."
         echo "*** WARNING: "
         echo "  $InstallPath is not a valid $ProdHomeName location."
         echo "  Please try again."
         return 1
      fi
   fi
   
   #XXXXX========================================================
   #  Test for valid ArcSDE installation location.
   #=============================================================
   if [ $ArcSDE = 1 ]
   then
      #===========================================================
      # Reset ArcSDEClientFolderTest to a file lib/jsde<92>_sdk.jar
      #===========================================================
      if [ "$ProductVersionStripped" = "90" -o "$ProductVersionStripped" = "91" -o "$ProductVersionStripped" = "92" ]
      then
         ArcSDEClientFileTest="lib/jsde${ProductVersionStripped}_sdk.jar"
      else
         ArcSDEClientFileTest="lib/jsde_sdk.jar"
      fi
      
      if [ -f $InstallPath/$ArcSDEFileTest -a $CurrentDB != $ArcSDKName ]
      then
         Validate_PreServicePack
         if [ $? = 1 ]
         then
            return 1
         else
            return 0
         fi
#      elif [ -d $InstallPath/$ArcSDEClientFolderTest -a $CurrentDB = $ArcSDKName ]
      elif [ -f $InstallPath/$ArcSDEClientFileTest -a $CurrentDB = $ArcSDKName ]
      then
         Validate_PreServicePack
         if [ $? = 1 ]
         then
            return 1
         else
            return 0
         fi
      else
         echo ""
         #echo "***WARNING:  $InstallPath/$ArcSDEFileTest does not exist."
         echo "*** WARNING:"
         echo "  $InstallPath is not a valid $ProdHomeName location."
         echo "  Please try again."
         return 1
      fi
   fi

   #XXXXX========================================================
   #  Test for valid ArcGIS installation location.
   #=============================================================
   if [ $ArcGIS = 1 ]
   then
      if [ "$ProductDispName" = "ArcGIS Server" ]
      then
         TestFile=$InstallPath/$ArcServerFileTest
      elif [ "$ProductDispName" = "ArcGIS Engine Runtime" ]
      then
         TestFile=$InstallPath/$ArcEngineRTFileTest
      elif [ "$ProductDispName" = "ArcReader" ]
      then
         TestFile=$InstallPath/$ArcReaderFileTest
      else
         echo ""
         echo "*** WARNING:"
         echo "  Unkown Product: $ProductDispName"
         return 1
      fi
         
      if test -f $TestFile
      then
         return 0
      else
         echo ""
         echo "*** WARNING: "
         echo "  $InstallPath is not a valid $ProductDispName location."
         echo "  Please try again."
         return 1
      fi
   fi
   
}


######################################################################
#=====================================================================
#  Validate_PreServicePack()
#
#  Based upon the product and the product installation path given by
#  the user, verify whether the required previous service pack or 
#  hot fix has been installed.
#=====================================================================
######################################################################
Validate_PreServicePack()
{
   if [ "$ProductVersion" = "9.3.1" ]
   then
      TestFile=$InstallPath/$QFETestFile
      if [ ! -f $TestFile ]
      then
         echo ""
         echo "*** WARNING:"
         echo "  $ProductName $ProductVersion was not detected in this location."
         echo "  You can either select another location to install"
         echo "  or quit to install $ProductName $ProductVersion first,"
         echo "  then come back to install this $QFEAbbreviated again."
         echo ""
         return 1
      else
         UpdateVersion=`Get_Update_Info`
         if [ $UpdateVersion != $ProductVersion ]
         then
            echo ""
            echo "*** WARNING:"
            echo "  $ProductName $ProductVersion was not detected in this location."
            echo "  You can either select another location to install"
            echo "  or quit to install $ProductName $ProductVersion first,"
            echo "  then come back to install this $QFEAbbreviated again."
            echo ""
            return 1
         fi
      fi
   fi
   
   if [ `LenChr "$ProductPreHotFix"` != 1 ]
   then
      TestFile=$InstallPath/$QFETestFile
      if [ ! -f $TestFile ]
      then
         echo ""
         echo "*** WARNING:"
         echo "  $ProductPHFTitle was not detected in this location."
         echo "  You can either select another location to install"
         echo "  or quit to install $ProductPHFTitle first,"
         echo "  then come back to install this $QFEAbbreviated again."
         echo ""
         return 1
      else
         TestOut=`grep -i $ProductPreHotFix $TestFile`
         if test $? -ne 0
         then
            echo ""
            echo "*** WARNING:"
            echo "  $ProductPHFTitle was not detected in this location."
            echo "  You can either select another location to install"
            echo "  or quit to install $ProductPHFTitle first,"
            echo "  then come back to install this $QFEAbbreviated again."
            echo ""
            return 1
         fi
      fi
   elif [ `LenChr "$ProductSerPack"` != 1 -a "$QFEAbbreviated" != "Update" ]
   then
      SPNumber=`Get_SP_Info`
      if [ $SPNumber -gt 0 ]
      then
         if [ $ProductSerPack -gt $SPNumber -a "$QFEAbbreviated" != "Service Pack" ]
         then
            echo ""
            echo "*** WARNING:"
            echo "  $ProductDispName $ProductVersion Service Pack $ProductSerPack was not detected in this location."
            echo "  You can either select another location to install"
            echo "  or quit to install the Service Pack $ProductSerPack first,"
            echo "  then come back to install this $QFEAbbreviated again."
            echo ""
            return 1
         elif [ $ProductSerPack -lt $SPNumber ]
         then
            echo ""
            echo "*** WARNING:"
            echo "  A newer Service Pack, $ProductDispName $ProductVersion Service Pack $SPNumber was detected in this location."
            echo "  You can either select another location to install or quit the install."
            echo ""
            return 1
         fi
      elif [ "$QFEAbbreviated" != "Service Pack" -a $ProductSerPack -gt 0 ]
      then
         echo ""
         echo "*** WARNING:"
         echo "  $ProductDispName $ProductVersion Service Pack $ProductSerPack was not detected in this location."
         echo "  You can either select another location to install"
         echo "  or quit to install the Service pack $ProductSerPack first,"
         echo "  then come back to install this $QFEAbbreviated again."
         echo ""
         return 1
      fi      
   fi
   return 0
}

######################################################################
#=====================================================================
#  Existing_Product_Bitset()
#
#  Based upon the product and the platform, determine the user's
#  installation bitset.
#=====================================================================
######################################################################
Existing_Product_Bitset()
{

   #XXXXX========================================================
   #  Determine file to check based upon product.
   #=============================================================
   if [ $ArcIMS = 1 ]
   then
      TestFile=$InstallPath/$ArcIMSFileTest
   elif [ $ArcInfo = 1 ] 
   then
      TestFile=$InstallPath/$ArcInfoFileTest
   elif [ $ArcSDE = 1 ]
   then
      if [ $CurrentDB != $ArcSDKName ]
      then
         TestFile=$InstallPath/$ArcSDEFileTest
      else
         if [ `uname` = "HP-UX" -a "$CurrentPlatform" !=  "hpia" ]
         then
            TestFile="${InstallPath}/lib/libsde${ProductVersionStripped}.sl"
            if test ! -f $TestFile
            then
               TestFile="${InstallPath}/lib/libsde.sl"
            fi
         else
            if test -f ${InstallPath}/lib/libsde${ProductVersionStripped}.so
            then
               TestFile="${InstallPath}/lib/libsde${ProductVersionStripped}.so"
            elif test -f ${InstallPath}/lib/libsde_64.so
            then
               TestFile="${InstallPath}/lib/libsde_64.so"
            elif test -f ${InstallPath}/lib/libsde${ProductVersionStripped}_64.so
            then
               TestFile="${InstallPath}/lib/libsde${ProductVersionStripped}_64.so"
            else
               TestFile="${InstallPath}/lib/libsde.so"
            fi
         fi
      fi
   elif [ $ArcGIS = 1 ]
   then
      case `uname` in
         OSF1)
            echo 64
         ;;
         *)
            echo 32
         ;;
      esac
      return
   fi  
   
   #XXXXX========================================================
   #  Based upon platform, perform a "file" test to determine
   #  whether the user's existing product install is 32 bit or
   #  64 bit.  Currently, Linux is always 32 bit and Tru64 is
   #  always 64 bit.
   #=============================================================
   #=============================================================
   # When file command can not get bit set information, set 
   # bit set value = 0.
   #=============================================================
   case `uname` in
      AIX)
         Value=`file $TestFile | awk '{print $2}' | cut -c1-2`
         if [ "$Value" = "64" ]
         then
            echo 64
         else
            if [ "$Value" = "32" ]
            then
               echo 32
            else
               echo 0
            fi
         fi
         ;;
      HP-UX)
         Value=`file $TestFile | awk '{print $2}' | cut -c5-6`
         if [ "$Value" = "64" ]
         then
            echo 64
         else 
            echo 32
         fi
         ;;
      Linux)
         Value=`file $TestFile | awk '{print $3}' | cut -c1-2`
         if [ "$Value" = "64" ]
         then
            echo 64
         else
            echo 32
         fi
         ;;
      OSF1)
         echo 64
         ;;
      SunOS)
         Value=`file $TestFile | awk '{print $3}' | cut -c1-2`
         if [ "$Value" = "64" ]
         then
            echo 64
         else
            if [ "$Value" = "32" ]
            then
               echo 32
            else
               echo 0
            fi
         fi
         ;;
   esac
   #============================================================
}


######################################################################
#=====================================================================
#  Validate_Selection()
#
#=====================================================================
######################################################################
Validate_Selection()
{
      
   #=============================================================
   #  Verify the the bitset of the QFE patch intended to be 
   #  installed matches the bitset of the user's existing 
   #  product.   
   #=============================================================
   #=============================================================
   # This Check only used for ArcSDE.
   # If ExistingProdBits = 0, which means we can not detect the 
   # bit set of existing porduct, prompt message to let users 
   # confirm the installation by themselves.
   #=============================================================
   IsBitCheckOK="yes"
   if [ "$ExistingProdBits" = "0" ]
   then
      break_loop1=0
      while [ $break_loop1 = 0 ]
      do
         echo " ==========Confirm installed $ProductDispName $ProductVersion $ArcSDESet bit set==========="
         echo " You are trying to install a $ProductBitSet bit $QFEAbbreviated of $ProductDispName $ProductVersion"
         echo " $ArcSDESet onto $InstallPath. "
         echo ""   
         echo "    \`y' to make sure the installed bit set matches the setup product bit"
         echo "    \`n' to reselect the installation path"
         echo ""

         if test `uname` = "Linux"
         then
            echo -n "Enter choice [y,n,q] (y): "
         else
            echo "Enter choice [y,n,q] (y): \c"
         fi
         read choice
   
         #==========================================================
         #  Perform actions based upon user's choice.
         #==========================================================
         case "X$choice" in
            X|Xy|XY)
               break_loop1=1
               HomeSetToInstall="yes"
               ;;
            Xn|XN)
               break_loop1=1
               IsBitCheckOK="no"
               ;;
            Xq|XQ)
               break_loop1=1
               HomeSetToInstall="yes"
               Voluntary_Quit
               ;;
         esac
      done
   else
      HomeSetToInstall="yes"
      if [ $ProductBitSet != $ExistingProdBits ]
      then
         echo "*** WARNING: "
         echo "  You are trying to install a $ProductBitSet bit $QFEAbbreviated of $ProductDispName $ProductVersion $ArcSDESet"
         echo "  onto an existing $ExistingProdBits bit version of $ProductDispName $ProductVersion $ArcSDESet."
         echo "  Please try again."
         echo ""
         HomeSetToInstall="no"
         IsBitCheckOK="no"
      fi
   fi
   #XXXXX========================================================
   #  For ArcSDE, verify that the selected QFE patch database is
   #  being installed upon the same user's database.   
   #=============================================================
   if [ $ArcSDE = 1 -a "$IsBitCheckOK" = "yes" -a $CurrentDB != $ArcSDKName ]
   then
      if [ "$ProductBitSet" = "64"  -a  `uname` = "AIX" ]
     then
         TheFile=libsde${CurrentDB}srvr${ProductVersionStripped}_64.so
      elif [ `uname` = "HP-UX" -a "$CurrentPlatform" !=  "hpia" ]
      then
         TheFile=libsde${CurrentDB}srvr${ProductVersionStripped}.sl
      else
         TheFile=libsde${CurrentDB}srvr${ProductVersionStripped}.so
      fi
      
      if [ ! -f $InstallPath/lib/$TheFile ]
      then
         TheExistDB="a different database"
         if test -f $InstallPath/lib/libsdeinfsrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdeinfsrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdeinfsrvr${ProductVersionStripped}_64.so 
         then
            TheExistDB="an Informix"
         fi
         if test -f $InstallPath/lib/libsdedb2srvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdedb2srvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdedb2srvr${ProductVersionStripped}_64.so 
         then
            TheExistDB="a DB2"
         fi
         if test -f $InstallPath/lib/libsdeora8isrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdeora8isrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdeora8isrvr${ProductVersionStripped}_64.so
         then
            TheExistDB="an Oracle_8i"
         fi
         if test -f $InstallPath/lib/libsdeora9isrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdeora9isrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdeora9isrvr${ProductVersionStripped}_64.so
         then
            TheExistDB="an Oracle_9i"
         fi
         if test -f $InstallPath/lib/libsdeora10gsrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdeora10gsrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdeora10gsrvr${ProductVersionStripped}_64.so
         then
            TheExistDB="an Oracle_10g"
         fi
         if test -f $InstallPath/lib/libsdeora11gsrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdeora11gsrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdeora11gsrvr${ProductVersionStripped}_64.so
         then
            TheExistDB="an Oracle_11g"
         fi
         if test -f $InstallPath/lib/libsdepgsrvr${ProductVersionStripped}.sl ||
            test -f $InstallPath/lib/libsdepgsrvr${ProductVersionStripped}.so ||
            test -f $InstallPath/lib/libsdepgsrvr${ProductVersionStripped}_64.so
         then
            TheExistDB="an PostgreSQL"
         fi
         echo "*** WARNING:"
         echo "  You are trying to install the $CurrentDBFormal version of the $ProductDispName $ProductVersion"
         echo "  $ArcSDESet $QFEAbbreviated onto $TheExistDB version."
         echo ""
         echo "  Please try again."
         echo ""
         HomeSetToInstall="no"
      fi
   fi

}


######################################################################
#=====================================================================
#  Update_TOC_File()
#
#  Create an updated TOC file based on what the user has installed in
#  their product HOME.
#=====================================================================
######################################################################
Update_TOC_File() 
{

   #=============================================================
   #  A QFE patch could contain files that are not currently in 
   #  the user's product installation.  This could be because of 
   #  one (or both) of two reasons:
   #
   #     1.  The patch contains brand-new files
   #     2.  The patch contains files for an optional package 
   #         (core), that the user hasn't installed.
   #
   #  In Case 1, we just give the user the new files.  In Case 2, 
   #  we only give them a "patched" version of the files they 
   #  have in their current product installation.
   #
   #  Here, we create an updated TOC file that only contains the 
   #  files that are to be applied to the user-specified product
   #  installation.  The "package" field in the updated TOC file 
   #  is set to either "new" if the file to be installed did not
   #  exist on the user's system before or "old" if an existing 
   #  file is being replaced.
   #=============================================================

   #XXXXX========================================================
   #  Get the process ID of the current process and create an
   #  updated TOC file in the /tmp directory (based on the PID).
   #=============================================================
   ProcessID=$$
   UpdatedTOCFile="/tmp/applypatch.toc.$ProcessID"

   #=============================================================
   #  Try to create the empty updated TOC file.  Print an error
   #  message, clean up and exit if it fails to create.
   #=============================================================
   cat /dev/null > $UpdatedTOCFile
   if test $? -ne 0
   then
      echo ""
      echo ""
      echo "*** ERROR: "
      echo "  Creating scratch file $UpdatedTOCFile."
      echo "  Make sure that at least 10K bytes are free in /tmp."
      Error_Exit
   fi

   #=============================================================
   #  Read through the user selected QFE patch TOC file.
   #=============================================================
   while read file size package bytes month day
   do
      #==========================================================
      #  If the current file exists in the user's install 
      #  location, or the file in the TOC is labelled as "new",
      #  then the file is considered valid for installation.
      #  It will be labelled as "old".
      #==========================================================
      if test -f $InstallPath/$file -o "$package" = "new" -o "$package" = "NEW"
      then
         if test -f $InstallPath/$file
         then
            package="old"
         fi
         
         #==========================================================
         #  Write out the appropriate information to the Updated
         #  TOC file.  If there is a write failure, print and error
         #  message, clean up and exit.
         #==========================================================
         echo $file $size $package $bytes $month $day >> $UpdatedTOCFile
         if test $? -ne 0
         then
            echo ""
            echo ""
            echo "*** ERROR:"
            echo "  Writing to scratch file $UpdatedTOCFile."
            echo "  Make sure that at least 10K bytes are free in /tmp."
            Error_Exit
         fi
      fi
   done < $PatchHome/$SelectedTOC

}
 

######################################################################
#=====================================================================
#  Check_Access_Rights()
#
#  Check to see if the directories containing the files to be
#  installed (from UpdatedTOCFile) exist and have write access.
#=====================================================================
######################################################################
Check_Access_Rights()
{

   #=============================================================
   #  Read through all the lines of the UpdatedTOCFile. 
   #=============================================================
   while read file size package bytes month day
   do
      #==========================================================
      #  If the directory to the current file does not exist,
      #  write out an error message and then exit. 
      #==========================================================
      if test ! -d `dirname $InstallPath/$file`
      then
         if [ "$package" != "new" -a "$package" != "NEW" ]
         then
            echo ""
            echo "*** ERROR: "
            echo "  `dirname $InstallPath/$file` does not exist."
            Error_Exit
         fi
      fi

      #==========================================================
      #  If the directory to the current file does not have
      #  write access, write out an error message and then exit. 
      #==========================================================
      if test ! -w `dirname $InstallPath/$file`
      then
         if [ "$package" != "new" -a "$package" != "NEW" ]
         then
            echo ""
            echo "*** ERROR: "
            echo "  No write access to `dirname $InstallPath/$file`."
            Error_Exit
         fi
      fi
            
   done < $UpdatedTOCFile

}


######################################################################
#=====================================================================
#  Check_Disk_Space()
#
#  Make sure that the minimum disk space needed to install the QFE
#  Patch is available.
#=====================================================================
######################################################################
Check_Disk_Space()
{

   #=============================================================
   #  No mater what is being done with the original files, the
   #  ProductHome must have sufficient space for the difference 
   #  between the original files and the new ESRI Patch files.  
   #  That is:
   #
   #     DF(ProductHome) > DU(patch_files) - DU(original_files) 
   #=============================================================
   FreeSpaceInDest=`MyDf $InstallPath`
   FreeSpaceInDest=`expr $FreeSpaceInDest / 1000`
   BytesReqd4Patch=`Size_Of_Patch`
   BytesReqd4Originals=`Size_Of_Originals`
   SpaceRequired=`expr $BytesReqd4Patch - $BytesReqd4Originals`
   SpaceRequired=`expr $SpaceRequired / 1000`
     
   #=============================================================
   #  If there is not enough space available, print out an error
   #  message, clean up and exit. 
   #=============================================================
   if [ $FreeSpaceInDest -lt $SpaceRequired ]
   then
      echo ""
      echo "*** ERROR: "
      echo "  There is not enough disk space to install this $QFEAbbreviated"
      echo "  in $InstallPath."
      echo ""
      echo "  Space Required :  $SpaceRequired MBytes."
      echo "  Space Available:  $FreeSpaceInDest MBytes."

      Error_Exit
   fi

}


######################################################################
#=====================================================================
#  MyDf() 
#
#  Determine available disk space (in KBytes).
#  Platform independant df.
#=====================================================================
######################################################################
MyDf() 
{
   #XXXXX========================================================
   #  Determine the available disk space - platform based.
   #=============================================================
   case `uname` in
      AIX)
         $DF -k $1 | tail -1 | awk '{print $3}'
         ;;
      HP-UX)
         $DF $1 | tail -1 | awk '{print $4}'
         ;;
      IRIX*)
         $DF -k $1 | tail -1 | awk '{print $5}'
         ;;
      Linux)
         CheckField=`$DF -k $1 | tail -1 | awk '{print NF}'`
         if [ $CheckField -lt 6 ]
         then
            $DF -k $1 | tail -1 | awk '{print $3}'
         else
            $DF -k $1 | tail -1 | awk '{print $4}'
         fi
         ;;
      OSF1)
         $DF -k $1 | tail -1 | awk '{print $4}'
         ;;
      SunOS)
         $DF -k $1 | tail -1 | awk '{print $4}'
         ;;
   esac
}


######################################################################
#=====================================================================
#  Size_Of_Patch() 
#
#  Add 2% to the total patch size to account for variations in the
#  du -sk output.
#=====================================================================
######################################################################
Size_Of_Patch() 
{

   #=============================================================
   #  Determine the total size of the patch based upon the 
   #  accumulation of sizes in the Updated TOC file.
   #=============================================================
   Total_Size=`Unadjusted_Size_Of_Patch`
   
   #=============================================================
   #  Increase by 2% to cover variations in the "du -sk" output.
   #=============================================================
   Total_Size=`expr $Total_Size + \( 2 \* $Total_Size / 100 \)`
   echo $Total_Size
   
}


######################################################################
#=====================================================================
#  Size_Of_Originals() 
#
#  Determine the total size of the files contained within the Updated
#  TOC using the size of the files already existing in the user's
#  product install.
#=====================================================================
######################################################################
Size_Of_Originals() 
{

   Total_Size=0
   
   #=============================================================
   #  Read through the Updated TOC file and add up the sizes of
   #  the files contained within it - using the size of the files
   #  already existing in the user's product install.
   #=============================================================
   cat $UpdatedTOCFile |
   (while read file size package bytes month day
   do
      if test -f $InstallPath/$file
      then
         File_Size=`MyDu $InstallPath/$file`
         Total_Size=`expr $Total_Size + $File_Size`
      fi
   done; echo $Total_Size)
   
}


######################################################################
#=====================================================================
#  Unadjusted_Size_Of_Patch() 
#
#  Add up the size of the files in the Updated TOC file to get a 
#  total patch size.
#=====================================================================
######################################################################
Unadjusted_Size_Of_Patch() 
{

   Total_Size=0
   
   #=============================================================
   #  Read through the Updated TOC file and add up the sizes of
   #  the files contained within it - to determine a Total_Size.
   #=============================================================
   cat $UpdatedTOCFile |
   (while read file file_size package bytes month day
   do
      Total_Size=`expr $Total_Size + $file_size`
   done; echo $Total_Size) 
   
}


######################################################################
#=====================================================================
#  MyDu() 
#
#  Determine the size (in KBytes) of the given file. 
#  Platform independent du.
#=====================================================================
######################################################################
MyDu() 
{

   du -sk $1 | awk '{print $1}'
   
}


######################################################################
#=====================================================================
#  Prompt_User_For_Backup()
#
#  Prompt the user to see if they would like to backup the original
#  files that will be replaced.
#=====================================================================
######################################################################
Prompt_User_For_Backup()
{

   #=============================================================
   #  Determine bytes required for the patch. 
   #=============================================================
   BytesReqd4Patch=`Size_Of_Patch`
   BytesReqd4Patch=`expr $BytesReqd4Patch / 1000`

   #=============================================================
   #  Describe backup process to user. 
   #=============================================================
   echo ""
   echo "  This $QFEAbbreviated will replace several files in your $ProductDispName $ProductVersion"
   echo "  $ArcSDESet installation directory.  We highly recommend to backup"
   echo "  the original files in case you decide you would like to "
   echo "  revert to them."
   echo ""
   echo "  You need $BytesReqd4Patch MBytes to install the $QFEAbbreviated with the backup."
   echo ""
   
   
   #XXXXX========================================================
   #  Continually prompt user and accept their input for 
   #  backup option until a valid option is selected.
   #=============================================================
   break_loop=0
   while [ $break_loop = 0 ]
   do
      echo ""
      echo "    \`y' to backup original files"
      echo "    \`n' to overwrite original files"
      echo ""

      if test `uname` = "Linux"
      then
        echo -n "Enter choice [y,n,q] (y): "
      else
        echo "Enter choice [y,n,q] (y): \c"
      fi
      read choice
   
      #==========================================================
      #  Perform actions based upon user's choice.
      #==========================================================
      case "X$choice" in
         X|Xy|XY)
            break_loop=1
            SaveFiles="yes"
            ;;
         Xn|XN)
            break_loop=1
            SaveFiles="no"
            ;;
         Xq|XQ)
            break_loop=1
            Voluntary_Quit
            ;;
      esac
   done

}


######################################################################
#=====================================================================
#  Validate_Save_Location()
#
#  If the user selected to backup the original files, then get a
#  backup location from the user and verify that it is a valid
#  location.
#=====================================================================
######################################################################
Validate_Save_Location()
{

   #=============================================================
   #  If the user selected to save backup the original files that
   #  will be replaced, print some details to the user and 
   #  prompt them for a backup location.  
   #=============================================================
   if [ $SaveFiles = "yes" ] 
   then
      echo ""
      echo ""
      echo "  By default the original files will be backed up in the $ProductDispName $ProductVersion"
      echo "  installation location.  The suffix '.orig' will be appended to"
      echo "  each file.  To save these files in a different location, please"
      echo "  enter the path below:"
      echo ""

      #XXXXX=====================================================
      #  Prompt the user for a SavePath (backup location). 
      #  Default to the ProductHome.
      #==========================================================
      if test `uname` = "Linux"
      then
         echo -n "Enter location to backup original files [q] ($InstallPath): " 
      else
         echo "Enter location to backup original files [q] ($InstallPath): \c" 
      fi
      read SavePath
   
      #==========================================================
      #  Clean up and exit if the user selected to quit.
      #==========================================================
      if [ "X$SavePath" = "Xq" -o "X$SavePath" = "XQ" ]
      then
         Voluntary_Quit
      fi

      #==========================================================
      #  If user hit <Return> at the prompt, set the SavePath
      #  (backup path) to the default - the InstallPath.
      #==========================================================
      if [ "X$SavePath" = "X" ]; then
         SavePath=$InstallPath
      fi

      #==========================================================
      #  Validate the SavePath (backup location) chosen by the
      #  user.  If the path is invalid, keep asking until they
      #  enter a valid path.
      #==========================================================
      Validate_Save_Path
      while [ $? != 0 ]
      do
         echo ""

         #XXXXX==================================================
         #  Prompt the user for a valid SavePath (backup
         #  location).
         #=======================================================
         if test `uname` = "Linux"
         then
            echo -n "Enter another location [q]: "
         else
            echo "Enter another location [q]: \c"
         fi
         read SavePath
         
         #=======================================================
         #  Clean up and exit if the user selected to quit.
         #=======================================================
         if [ "X$SavePath" = "Xq" -o "X$SavePath" = "XQ" ];
         then
            Voluntary_Quit
         fi
         
         #=======================================================
         #  Keep prompting user for a valid SavePath (backup
         #  location) path for as long as they do not enter one.
         #=======================================================
         while [ "X$SavePath" = "X" ]
         do

            #XXXXX===============================================
            #  Promp the user for a valid SavePath (backup
            #  location).
            #====================================================
            if test `uname` = "Linux"
            then
               echo -n "Enter another location [q]: "
            else
               echo "Enter another location [q]: \c"
            fi
            read SavePath
            
            #====================================================
            #  Clean up and exit if the user selected to quit.
            #====================================================
            if [ "X$SavePath" = "Xq" -o "X$SavePath" = "XQ" ];
            then
               Voluntary_Quit
            fi
            
         done
         
         #=======================================================
         #  Validate the SavePath (backup location) chosen by
         #  the user.
         #=======================================================
         Validate_Save_Path
         
      done

   fi

}


######################################################################
#=====================================================================
#  Validate_Save_Path()
#
#  Validate that the save path exists and is writeable.
#=====================================================================
######################################################################
Validate_Save_Path() 
{

   return_status=0

   #=============================================================
   #  Make sure the backup location exists.
   #=============================================================
   if test ! -d $SavePath 
   then
      echo ""
      echo "*** WARNING: "
      echo "  $SavePath does not exist."
      return 1
   fi

   #=============================================================
   #  Make sure the backup location is writeable.
   #=============================================================
   if test ! -w $SavePath 
   then
      echo ""
      echo "*** WARNING: "
      echo "  You do not have write access to $SavePath."
      return 1
   fi


   #=============================================================
   #  Make sure there is sufficient disk space to store the
   #  original files.
   #
   #  There are 2 cases:
   #
   #     1.  Storing originals in the ProductHome itself or on 
   #         the same disk drive as the ProductHome.
   #	     In this case, we need to make sure that the 
   #         ProductHome drive has sufficient space for the patch 
   #         files + existing originals.  That is:
   #
   #		DF(ProductHome) > DU(patch_files)
   #
   #     2.  Storing originals on a different disk drive than 
   #         the ProductHome.
   #         In this case, we need to make sure this other drive
   #         has sufficient space for the originals:
   #
   #		DF($SavePath) > DU(original_files)
   #
   #     Note:  We verified earlier that the ProductHome has 
   #            room for any extra space needed to install the 
   #            patch files.
   #
   #=============================================================
   FreeSpaceInDest=`MyDf $InstallPath`
   FreeSpaceInDest=`expr $FreeSpaceInDest / 1000`
   BytesReqd4Patch=`Size_Of_Patch`
   BytesReqd4Patch=`expr $BytesReqd4Patch / 1000`
   BytesReqd4Originals=`Size_Of_Originals`
   BytesReqd4Originals=`expr $BytesReqd4Originals / 1000`
   FreeSpaceInSavePath=`MyDf $SavePath`
   FreeSpaceInSavePath=`expr $FreeSpaceInSavePath / 1000`   
	
   #=============================================================
   #  Case 1 - save originals in the ProductHome.
   #=============================================================
   if [ `Drive_Name $InstallPath` = `Drive_Name $SavePath` ] 
   then
      if [ $FreeSpaceInDest -lt $BytesReqd4Patch ]
      then
         echo ""
         echo "*** WARNING: "
         echo "  Not enough space to store originals on /`Drive_Name $SavePath`"
         echo ""
         echo "  Space Required : $BytesReqd4Patch MBytes."
         echo "  Space Available: $FreeSpaceInDest MBytes."

         return_status=1
      fi


   #=============================================================
   #  Case 2 - original somewhere other than in the ProductHome.
   #=============================================================
   else

      if [ $FreeSpaceInSavePath -lt $BytesReqd4Originals ]
      then
         echo ""
         echo "*** WARNING:"
         echo "  Not enough space to store originals on /`Drive_Name $SavePath`"
         echo ""
         echo "  Space Required : $BytesReqd4Originals MBytes."

         return_status=1
      fi
   fi

   return $return_status
   
}


######################################################################
#=====================================================================
#  Drive_Name() 
#
#  Determine the total size of the files contained within the Updated
#  TOC using the size of the files already existing in the user's
#  product install.
#=====================================================================
######################################################################
Drive_Name()
{

   current_dir=`pwd`
   cd $1
   pwd | cut -d/ -f2
   cd $current_dir
   
}


######################################################################
#=====================================================================
#  Confirm_Settings()
#
#  Display the current selections made by the user and have the user
#  choose to confirm or change the settings.
#=====================================================================
######################################################################
Confirm_Settings()
{

   #XXXXX========================================================
   #  Display the current selections made by the user.  
   #=============================================================
   echo ""
   echo "  Confirm Settings"
   echo "  ==================================================================="
   #echo "  Product to patch:        $ProductDispName $ProductVersion $ProductSerPack"
   if [ $ArcSDE = 1 ] 
   then
      #echo "  Product to patch:        $ProductDispName $ProductVersion $ArcSDESet $ProductSerPack"
      echo "  Product to update:        $ProductDispName $ProductVersion $ArcSDESet"
      #echo "  Platform to patch:       $CurrentPlatformUC $ProductBitSet-bit"
      echo "  Platform to update:       $ProductPlatform $ProductBitSet-bit"
      if [ $CurrentDB != $ArcSDKName ]
      then
         echo "  Database to update:       $CurrentDBFormal"
      fi
   else
      #echo "  Product to patch:        $ProductDispName $ProductVersion $ProductSerPack"
      echo "  Product to update:        $ProductDispName $ProductVersion"
      #echo "  Platform to patch:       $CurrentPlatformUC"
      echo "  Platform to update:       $ProductPlatform"
   fi
   echo "  Location to update:       $InstallPath"
   echo "  Backup original files:   $SaveFiles"
   if [ $SaveFiles = "yes" ] 
   then
      if [ $InstallPath = $SavePath ] 
      then
         echo "  Backup originals in:     $InstallPath"
      else
         echo "  Backup original files to:  $SavePath/${ProductName}_${ProductVersion}.orig"
      fi
   fi
   
   
   #XXXXX========================================================
   #  Continually loop through the prompting of the user about
   #  the selections displayed until they make a valid choice.  
   #=============================================================
   break_loop=0
   while [ $break_loop = 0 ]
   do
      echo ""
      echo "     \`y' to continue with these settings"
      echo "     \`c' to change settings"
      echo "     \`q' to exit without applying this $QFEAbbreviated"
      echo ""
      if test `uname` = "Linux"
      then
         echo -n "Enter choice [y,c,q] (y): "
      else
         echo "Enter choice [y,c,q] (y): \c"
      fi
      read choice
    
      #==========================================================
      #  Perform actions based upon user's choice.
      #==========================================================
      case "X$choice" in
         X|Xy|XY)
            break_loop=1 
            AllSetToInstall="yes"
            ;;
         Xc|XC)
            break_loop=1
            echo ""
            ;;
	 Xq|XQ)
	    Voluntary_Quit;
	    
	    ;;
      esac
   done

}


######################################################################
#=====================================================================
#  Perform_Backup()
#
#  Backup the original files to the user specified location.  If there
#  is a failure during backup, restore the originals and exit on 
#  error.
#=====================================================================
######################################################################
Perform_Backup()
{

   #=============================================================
   #  If the user selected to backup the original files...proceed
   #  to back them up.  
   #=============================================================
   if test "$SaveFiles" = "yes"
   then

      #==========================================================
      #  If the product install path is the same as the user
      #  selected backup path...proceed to backup original files.
      #==========================================================
      if test "$InstallPath" = "$SavePath"
      then

         #=======================================================
         #  Rename the original files in the ProductHome.
         #=======================================================
         
         #=======================================================
         #  Indicate to the user that the original files are
         #  being renamed (for backup).
         #=======================================================
         echo ""
         echo "  Renaming original files ..."

         #=======================================================
         #  Walk through the Updated TOC file and rename the
         #  files in the ProductHome area.
         #=======================================================
         while read file size package bytes month day
         do
         
            #====================================================
            #  If the current file indicator is "old"...proceed 
            #  to back it up.
            #====================================================
            if test $package = "old"
            then

               #=================================================
               #  If an old backup copy exists, remove it before
               #  the rename.  This will work even if it's 
               #  read-only or root owned.
               #=================================================
               if test -f $InstallPath/$file.orig
               then
                  rm -f $InstallPath/$file.orig
               fi
            
               #=================================================
               #  Save the original file (via mv).
               #=================================================
               mv $InstallPath/$file $InstallPath/$file.orig
               
               #=================================================
               #  If the backup of the original file failed, we
               #  need to restore the original files that have
               #  already been backed up.
               #=================================================
               if test $? -ne 0 
               then
                  echo "*** ERROR: "
                  echo "  Renaming $InstallPath/$file to $InstallPath/$file.orig."
                  echo "  Restoring original files ..."
                  
                  #==============================================
                  #  Set CurrentFile to the current file.
                  #==============================================
                  CurrentFile=$file  
                  
                  #==============================================
                  #  Walk through the Updated TOC file to
                  #  restore.
                  #==============================================
                  while read file size package bytes month day
                  do
                  
                     #===========================================
                     #  If the current file matches the
                     #  CurrentFile saved off earlier (problem
                     #  file), indicate that the original files
                     #  have been restored and exit processing.
                     #===========================================
                     if test $CurrentFile = $file
                     then
                        echo "            Original files restored."
                        Error_Exit
                     
                     #===========================================
                     #  Otherwise, if the current file does not
                     #  matche the CurrentFile saved off earlier 
                     #  (problem file), we need to restore it.
                     #===========================================
                     elif test $package = "old"
                     then
                     
                        #========================================
                        #  Restore the current file with the 
                        #  original that was previously saved
                        #  off (via mv).
                        #========================================
                        mv $InstallPath/$file.orig $InstallPath/$file
                        
                        #========================================
                        #  If the restore of the current file
                        #  failed, print an error message to the
                        #  user and exit processing.
                        #========================================
                        if test $? -ne 0 
                        then
                           echo "*** ERROR:"
                           echo "  Renaming $InstallPath/$file.orig to $InstallPath/$file"
                           echo "  Original files could not be restored."
                           Error_Exit
                        fi
                     fi
                  done < $UpdatedTOCFile
                  
                  #==============================================
                  #  If we made it here, something went wrong.
                  #  We should have taken one of the exits above.
                  #  Print an error message to the user and 
                  #  exit processing.
                  #==============================================
                  echo "*** ERROR:"
                  echo "  An error occured while trying to restore the original files."
                  Error_Exit
               fi
            fi
         done < $UpdatedTOCFile
   
   
      #==========================================================
      #  Otherwise, the user specified a backup path other than 
      #  the product install path...proceed to backup original 
      #  files.
      #==========================================================
      else
   
         #=======================================================
         #  Save the original files at the location specified by
         #  the user.
         #=======================================================
         
         #=======================================================
         #  Indicate to the user that the original files are 
         #  being saved to the location they specified.
         #=======================================================
         echo ""
         echo "  Saving original files to $SavePath ..."
      
         #=======================================================
         #  Set the SavePath (backup location).
         #=======================================================
         SavePath="$SavePath/${ProductName}_${ProductVersion}.orig"
         
         #=======================================================
         #  Walk through the Updated TOC file and save the files
         #  in the user specified backup location.
         #=======================================================
         while read file size package bytes month day
         do
            
            #====================================================
            #  If the current file indicator is "old"...proceed 
            #  to back it up.
            #====================================================
            if test $package = "old"
            then
            
               #=================================================
               #  If the current file's backup location directory
               #  doesn't exit, create it.
               #=================================================
               if [ ! -d `dirname $SavePath/$file` ] 
               then
                  mkdir -p `dirname $SavePath/$file`
                  
                  #==============================================
                  #  If failed to create the directory, print an
                  #  error message to the user and exit 
                  #  processing.
                  #==============================================
                  if test $? -ne 0
                  then
                     echo "*** ERROR:"
                     echo "  Creating directory `dirname $SavePath/$file`."
                     Error_Exit
                  fi
               fi
               
               #=================================================
               #  If an old backup copy exists, remove it before 
               #  the copy.  This will work even if it's 
               #  read-only or root owned.
               #=================================================
               if test -f $SavePath/$file
               then
                  rm -f $SavePath/$file
               fi
            
               #=================================================
               #  Save (backup) the original file.
               #=================================================
               cp -p $InstallPath/$file $SavePath/$file
               
               #=================================================
               #  If the file copy failed, print an error message
               #  to the user and exit processing.
               #=================================================
               if test $? -ne 0
               then
                  echo "*** ERROR:"
                  echo "  Copying $InstallPath/$file to $SavePath/$file."
                  Error_Exit
               fi
            fi
         done < $UpdatedTOCFile
      fi

   fi

}


######################################################################
#=====================================================================
#  Remove_NonWritable_Files()
#
#  Walk through the Updated TOC file and remove non-writable original
#  files.
#
#  We know we have full access rights to the directories but some of 
#  the original files to be replaced may be "read only" or root-owned
#  with the "set-user-id" bit set.  These cannot be updated by the 
#  tar command unless the old version is first removed, so remove 
#  them now.
#=====================================================================
######################################################################
Remove_NonWritable_Files()
{

   #=============================================================
   #  Walk through the Updated TOC file.  If the current file
   #  is not writable, force remove it.  
   #=============================================================
   while read file size package bytes month day
   do
      if test ! -w $InstallPath/$file
      then
         rm -f $InstallPath/$file
         # no error check here; wait and see if the tar works
      fi
   done < $UpdatedTOCFile

}


######################################################################
#=====================================================================
#  Apply_The_Patch()
#
#  Uncompresses, untars and installs the ESRI Patch files in the 
#  appropriate location.
#=====================================================================
######################################################################
Apply_The_Patch()
{

   #=============================================================
   #  Indicate to the user that the ESRI Patch is being applied.  
   #=============================================================
   echo "  Applying the $QFEAbbreviated..."

   #XXXXX========================================================
   #  This is hoaky, but necessary!   zcat will not uncompress a 
   #  file without a .Z (upper-Case) extension.  And, we cannot 
   #  create a CD-ROM with mixed case filenames.  So, we create 
   #  the ESRI Patch file on the CD with a lower-case .z 
   #  extension, and then this:
   #=============================================================
   TmpPatchFile=/tmp/applypatch.tar.Z
   rm -f $TmpPatchFile
   
   #XXXXX========================================================
   #  Create a link with upper-case .Z pointing to compressed
   #  tar file with lower-case .z:
   #    /tmp/applypatch.tar.Z -> $PatchHome/..../$ApplyPatchTAR
   #=============================================================
   if [ $ArcSDE = 1 ]
   then
      if [ $ProductBitSet = "64" -a $CurrentPlatform != $Tru64Platform ]
      then
         ln -s $PatchHome/$CurrentPlatform$ProductBitSet.$CurrentDB/$ApplyPatchTAR $TmpPatchFile
      else
         ln -s $PatchHome/$CurrentPlatform.$CurrentDB/$ApplyPatchTAR $TmpPatchFile
      fi
   else
      if [ $ArcGIS = 1 ]
      then
         ln -s $PatchHome/$CurrentPlatform.$ProductFolderName/$ApplyPatchTAR $TmpPatchFile
      else
         ln -s $PatchHome/$CurrentPlatform/$ApplyPatchTAR $TmpPatchFile
      fi
   fi

   #=============================================================
   #  If failure to create the link, print an error message,
   #  restore and exit.
   #=============================================================
   if test $? -ne 0
   then
      echo ""
      echo "*** ERROR:"
      echo "  Creating scratch link $TmpPatchFile."
      echo "  Make sure that at least 10K bytes are free in /tmp."
      Restore_And_Exit
   fi

   #=============================================================
   #  cd to the InstallPath.
   #=============================================================
   cd $InstallPath > /dev/null 2>&1
   
   #=============================================================
   #  Call the function to uncompress, untar and install the QFE
   #  Patch files in the Install location.
   #=============================================================
   Extract_The_Patch
   
   #=============================================================
   #  If the previous function call had a failure, it was due
   #  to the un-tarring.  Print an error message to the user, 
   #  restore and exit.
   #=============================================================
   if test $? -ne 0
   then
      echo "*** ERROR:"
      echo "  The tar command being used to install the $QFEAbbreviated files failed"
      Restore_And_Exit
   fi
   
   #=============================================================
   #  Return to the original working directory.
   #=============================================================
   cd $CurrentWorkingDir > /dev/null 2>&1

}


######################################################################
#=====================================================================
#  Restore_And_Exit() 
#
#  The installation of the patch failed.  This routine is only called 
#  when some of the patch files may have already been installed, 
#  leaving the ProductHome in a ragged state.  If the user specified 
#  backing up the original files, give them the option of putting 
#  things back the way they were.
#=====================================================================
######################################################################
Restore_And_Exit() 
{


   #=============================================================
   #  Indicate to the user that the ESRI Patch has failed and it
   #  will need to be re-run.
   #=============================================================
   echo ""
   echo "             The $QFEAbbreviated ($QFEVersion) installation has failed."
   echo "             You will have to re-run applyupdate to install $QFEVersion."
   echo ""
  
   #=============================================================
   #  If the user specified to backup the original files...
   #  proceed to restore.
   #=============================================================
   if [ $SaveFiles = "yes" ]
   then

      #XXXXX=====================================================
      #  Prompt the user to either restore or quit.
      #==========================================================
      echo "             Press 'y' to restore the original files or 'q' to quit."
      echo ""

      if test `uname` = "Linux"
      then
         echo -n "Restore original files? [y,q] (y): "
      else
         echo "Restore original files? [y,q] (y): \c"
      fi
      read choice

      #==========================================================
      #  Perform actions based upon users choice.
      #==========================================================
      case "X$choice" in
         Xn|XN)
            Clean_Up
            exit 1
            ;;
         Xq|XQ)
            Voluntary_Quit
            ;;
      esac

      #==========================================================
      #  Indicate to the user the files are being restored.
      #==========================================================
      echo "  Restoring original files ..."
      
      #==========================================================
      #  If the product install path is the same as the user
      #  selected backup path...proceed to restore the original
      #  files.
      #==========================================================
      if [ $InstallPath = $SavePath ]
      then
      
         #=======================================================
         #  Walk through the Updated TOC file and restore files
         #  as necessary.
         #=======================================================
         while read file size package bytes month day
         do
         
            #====================================================
            #  If the current file indicator is "old"...proceed 
            #  to restore it.
            #====================================================
            if test $package = "old"
	    then
	    
	       #=================================================
               #  If a target file exists, remove it before the
               #  restore.  This will work even if it's read-only
               #  or root owned.
               #=================================================
               if test -f $InstallPath/$file
               then
                  rm -f $InstallPath/$file
               fi
            
               #=================================================
               #  Restore the current file (via mv).
               #=================================================
               mv $InstallPath/$file.orig $InstallPath/$file
               
               #=================================================
               #  If unable to restore the current file, print an
               #  error message to the user and exit processing.
               #=================================================
               if test $? -ne 0
               then
                  echo "*** ERROR:"
                  echo "  Renaming $InstallPath/$file.orig to $InstallPath/$file"
                  echo "  Could not restore original files."
                  echo ""
                  Clean_Up
                  exit 1
               fi
	    fi
         done < $UpdatedTOCFile
         
         #=======================================================
         #  Successful restore.  Indicate to the user that the
         #  original files were restored.
         #=======================================================
         echo "  Original files restored."


      #==========================================================
      #  Otherwise, the user specified a backup path other than 
      #  the product install path...proceed to restore the
      #  original files.
      #==========================================================
      else

         #=======================================================
         #  Walk through the Updated TOC file and restore files
         #  as necessary.
         #=======================================================
         while read file size package bytes month day
         do
            #====================================================
            #  If the current file indicator is "old"...proceed 
            #  to restore it.
            #====================================================
            if test $package = "old"
	    then

               #=================================================
               #  If a target file exists, remove it before the 
               #  restore.  This will work even if it's read-only 
               #  or root owned.
               #=================================================
               if test -f $InstallPath/$file
               then
                  rm -f $InstallPath/$file
               fi
            
               #=================================================
               #  Restore the original file.
               #=================================================
               cp -p $SavePath/$file $InstallPath/$file
               
               #=================================================
               #  If unable to restore the current file, print an
               #  error message to the user and exit processing.
               #=================================================
               if test $? -ne 0
               then
                  echo "*** ERROR:"
                  echo "  Copying $SavePath/$file to $InstallPath/$file"
                  echo "  Could not restore original files."
                  echo " "
                  Clean_Up
                  exit 1
               fi
	    fi
         done < $UpdatedTOCFile
         
         #=======================================================
         #  Successful restore.  Indicate to the user that the
         #  original files were restored.
         #=======================================================
         echo "  Original files restored."

      fi
   fi
  
   #=============================================================
   #  Clean up and exit processing.
   #=============================================================
   Clean_Up
   exit 1
   
}


######################################################################
#=====================================================================
#  Extract_The_Patch() 
#
#  Extracts files from compressed tar file.
#=====================================================================
######################################################################
Extract_The_Patch() 
{

   #=============================================================
   #  Un-tar the listed files.  The check for errors is 
   #  performed by the caller.  The exit status is the final 
   #  status of the tar.
   #=============================================================
   ( $ZCAT $TmpPatchFile | $TAR xf - `Files_To_Tar` ) >/dev/null 2>&1
   ( $ZCAT $TmpPatchFile | $TAR xf - `Files_To_Tar_1` ) >/dev/null 2>&1
   ( $ZCAT $TmpPatchFile | $TAR xf - `Files_To_Tar_2` ) >/dev/null 2>&1
   ( $ZCAT $TmpPatchFile | $TAR xf - `Files_To_Tar_3` ) >/dev/null 2>&1
   
}


######################################################################
#=====================================================================
#  Files_To_Tar() 
#
#  Generates and returns a list of files to be un-tar'd (using the
#  Updated TOC file).
#=====================================================================
######################################################################
Files_To_Tar() 
{

   #=============================================================
   #  Return a list of all the files to be un-tar'd.
   #=============================================================
   FilesToTAR=""
   theIndex=0
   cat $UpdatedTOCFile | 
   (while read file size package bytes month day
   do
      theIndex=`expr $theIndex + 1`
      if [ $theIndex -lt 500 ]
      then
         FilesToTAR="$FilesToTAR $file"
      fi
   done; echo $FilesToTAR) 
   
}

######################################################################
#=====================================================================
#  Files_To_Tar_1() 
#
#  Special for updated files more than 500 and less than 1000
#  Generates and returns a list of files to be un-tar'd (using the
#  Updated TOC file).
#=====================================================================
######################################################################
Files_To_Tar_1() 
{

   #=============================================================
   #  Return a list of all the files to be un-tar'd.
   #=============================================================
   FilesToTAR=""
   theIndex=0
   cat $UpdatedTOCFile | 
   (while read file size package bytes month day
   do
      theIndex=`expr $theIndex + 1`
      if [ $theIndex -gt 499 -a $theIndex -lt 1000 ]
      then
        FilesToTAR="$FilesToTAR $file"
      fi
   done; echo $FilesToTAR) 
   
}

######################################################################
#=====================================================================
#  Files_To_Tar_2() 
#
#  Special for updated files more than 1000 and less than 1500
#  Generates and returns a list of files to be un-tar'd (using the
#  Updated TOC file).
#=====================================================================
######################################################################
Files_To_Tar_2() 
{

   #=============================================================
   #  Return a list of all the files to be un-tar'd.
   #=============================================================
   FilesToTAR=""
   theIndex=0
   cat $UpdatedTOCFile | 
   (while read file size package bytes month day
   do
      theIndex=`expr $theIndex + 1`
      if [ $theIndex -gt 999 -a $theIndex -lt 1500 ]
      then
        FilesToTAR="$FilesToTAR $file"
      fi
   done; echo $FilesToTAR) 
   
}

######################################################################
#=====================================================================
#  Files_To_Tar_3() 
#
#  Special for updated files more than 1500
#  Generates and returns a list of files to be un-tar'd (using the
#  Updated TOC file).
#=====================================================================
######################################################################
Files_To_Tar_3() 
{

   #=============================================================
   #  Return a list of all the files to be un-tar'd.
   #=============================================================
   FilesToTAR=""
   theIndex=0
   cat $UpdatedTOCFile | 
   (while read file size package bytes month day
   do
      theIndex=`expr $theIndex + 1`
      if [ $theIndex -gt 1499 ]
      then
        FilesToTAR="$FilesToTAR $file"
      fi
   done; echo $FilesToTAR) 
   
}



















######################################################################
#=====================================================================
#  Verify_The_Install()
#
#  Uncompresses, untars and installs the ESRI Patch files in the 
#  appropriate location.
#=====================================================================
######################################################################
Verify_The_Install()
{

   #=============================================================
   #  Print a message to the user indicating that the ESRI Patch
   #  has been installed.
   #=============================================================
   #echo ""
   #echo "  $QFEVersion has been installed."
   #echo ""

   #XXXXX========================================================
   #  Prompt the user to verify the ESRI Patch installation.
   #=============================================================
   #if test `uname` = "Linux"
   #then
   #  echo -n "Press the enter key to verify the installation [q]: "
   #else
   #  echo "Press the enter key to verify the installation [q]: \c"
   #fi
   #read choice
   
   
   #=============================================================
   #  Restore, clean up and exit if the user selected to quit.
   #=============================================================
   #if [ "X$choice" = "Xq" -o "X$choice" = "XQ" ];
   #then
   #   Restore_And_Exit
   #fi
   
   #=============================================================
   #  Print a message to the user indicating that the ESRI Patch
   #  is being verified.
   #=============================================================
   echo "  Verifying $QFEAbbreviated installation ..."

   #=============================================================
   #  Call function to validate the ESRI Patch files were 
   #  properly installed.  Get an account of any errors.
   #=============================================================
   error_count=`Validate_The_Patch`
   
   #=============================================================
   #  If there were errors in the validation:  list the errors,
   #  restore and exit.
   #=============================================================
   if test $error_count -ne 0 
   then
      List_Validation_Errors
      Restore_And_Exit
      
   #=============================================================
   #  Otherwise, no errors.  Print a message to the user 
   #  indicating the ESRI Patch was successfully installed.
   #=============================================================
   else
#      if [ "$QFEAbbreviated" = "Service Pack" ]
#      then
#         Update_ServicePack_Info
#         if test $? -ne 0
#         then
#            Restore_And_Exit
#         fi
#      fi
      
      Update_QFE_Info
      if test $? -ne 0
      then
         Restore_And_Exit
      fi
      
      echo ""
      #echo "  The $QFEAbbreviated ($QFEVersion) has been successfully applied to $ProductDispName $ProductVersion $ArcSDESet $ProductSerPack."
      if [ $ArcSDE = 1 ]
      then
        echo "  The $QFEAbbreviated ($QFEVersion) has been successfully applied to $ProductDispName $ProductVersion $ArcSDESet."
      else
        echo "  The $QFEAbbreviated ($QFEVersion) has been successfully applied to $ProductDispName $ProductVersion."
      fi
      echo ""
   fi

}


######################################################################
#=====================================================================
#  Validate_The_Patch() 
#
#  Check that the patch was installed correctly by inspecting the 
#  ESRI Patch files installed.
#=====================================================================
######################################################################
Validate_The_Patch() 
{

   #=============================================================
   #  Initialize the error count.
   #=============================================================
   error_count=0
   
   #=============================================================
   #  Read through the Updated TOC file.
   #=============================================================
   cat $UpdatedTOCFile |
   (while read file size package bytes month day
   do
      
      #==========================================================
      #  If the current file exists in the appropriate install 
      #  location: 
      #==========================================================
      if test -f $InstallPath/$file
      then
      
         #=======================================================
         #  Get the number of bytes of the file; get the month of
         #  the file; get the day of the file (from the 
         #  installation location).
         #=======================================================
         f5=`Get_File_Bytes $InstallPath/$file`
         f6=`Get_File_Month $InstallPath/$file`
         f7=`Get_File_Day $InstallPath/$file`
	       
         #=======================================================
         #  Suppress the month and day check to avoid 
         #  international time zone issues.
         #=======================================================
         #if test $bytes -ne $f5 -o "$month" != "$f6" -o $day -ne $f7

         #=======================================================
         #  If the current file byte size in the Updated TOC file
         #  does not match the file byte size of the 
         #  correspondingfile in the installation location: 
         #  increment the error count.
         #=======================================================
         if test $bytes -ne $f5
         then
            error_count=`expr $error_count + 1`
         fi
      
      #==========================================================
      #  Otherwise, the file doesn't exist in the installation
      #  location:  increment the error count.
      #==========================================================
      else
         if test ! -d $InstallPath/$file
         then
            error_count=`expr $error_count + 1`
         fi
      fi
   
   #=============================================================
   #  Echo the error count at the completion of the loop.
   #=============================================================
   done; echo $error_count)
   
}


######################################################################
#=====================================================================
#  List_Validation_Errors() 
#
#  List the files that were not installed correctly by inspecting the 
#  file size on the ESRI Patch files in the installation location.
#=====================================================================
######################################################################
List_Validation_Errors() 
{

   #=============================================================
   #  Read through the Updated TOC file.
   #=============================================================
   while read file size package bytes month day
   do
   
      #==========================================================
      #  If the current file exists in the appropriate install 
      #  location: 
      #==========================================================
      if test -f $InstallPath/$file
      then
         
         #=======================================================
         #  Get the number of bytes of the file; get the month of
         #  the file; get the day of the file (from the 
         #  installation location).
         #=======================================================
         f5=`Get_File_Bytes $InstallPath/$file`
         f6=`Get_File_Month $InstallPath/$file`
         f7=`Get_File_Day $InstallPath/$file`

         #=======================================================
         #  Suppress the month and day check to avoid 
         #  international time zone issues.
         #=======================================================
         #if test $bytes -ne $f5 -o "$month" != "$f6" -o $day -ne $f7
         
         #=======================================================
         #  If the current file byte size in the Updated TOC file
         #  does not match the file byte size of the 
         #  correspondingfile in the installation location: 
         #  print error message to the user indicating the 
         #  problem file, its expected size and it's actual size.
         #=======================================================
         if test $bytes -ne $f5 
         then
            echo "  *** Incorrect size for file:  "$InstallPath/$file 
            echo "         expected: $bytes 
            echo "         actual:   $f5
         fi
         
      #==========================================================
      #  Otherwise, the file doesn't exist in the installation
      #  location:  print error message to the user indicating
      #  the missing file.
      #==========================================================
      else
         echo "  *** File missing:  "$InstallPath/$file
      fi
      
   done < $UpdatedTOCFile
   
}


######################################################################
#=====================================================================
#  Get_File_Bytes() 
#
#  Get the size in bytes of the specified file.
#=====================================================================
######################################################################
Get_File_Bytes() 
{
   
   $LS -l $1 | ( read f1 f2 f3 f4 f5 f6 f7 f8; echo $f5 )
   
}


######################################################################
#=====================================================================
#  Get_File_Month() 
#
#  Get the month portion of the date of the specified file.
#=====================================================================
######################################################################
Get_File_Month() 
{

   $LS -l $1 | ( read f1 f2 f3 f4 f5 f6 f7 f8; echo $f6 )

}


######################################################################
#=====================================================================
#  Get_File_Day() 
#
#  Get the day portion of the date of the specified file.
#=====================================================================
######################################################################
Get_File_Day() 
{

   $LS -l $1 | ( read f1 f2 f3 f4 f5 f6 f7 f8; echo $f7 )
   
}

######################################################################
#=====================================================================
#  Update_QFE_Info() 
#
#  Update the .ESRI_<Product>_PATCH_LOG with the current QFE information.
#=====================================================================
######################################################################
Update_QFE_Info() 
{
   ProcessID=$$

   TmpQFEFile=/tmp/applypatch.$ProductName.qfe.$ProcessID
   rm -f $TmpQFEFile
   touch $TmpQFEFile

   #==========================================================
   # Insert the current QFE info to the head of the info file:
   # .ESRE_<Product>_PATCH_LOG.
   #==========================================================
   echo "#START"               		>> $TmpQFEFile
   echo "QFE_ID: $QFENumber"   		>> $TmpQFEFile
   echo "QFE_TYPE: $QFEAbbreviated"		>> $TmpQFEFile
   if [ "$QFEAbbreviated" = "Service Pack" -o "$QFEAbbreviated" = "Update" ]
   then
      echo "QFE_TITLE: $ProductSerPack" 	>> $TmpQFEFile
   else
      echo "QFE_TITLE: $QFEVersion"        	>> $TmpQFEFile
   fi
   echo "INSTALL_TIME: `date '+%m/%d/%y %H:%M:%S'`" 	>> $TmpQFEFile
   echo "#END"				>> $TmpQFEFile
   echo ""			       		>> $TmpQFEFile
     
   QFEExist=0
   if [ -f $InstallPath/$QFETestFile ]
   then
      QFEExist=1
      cat $InstallPath/$QFETestFile	>> $TmpQFEFile 
      rm -f $InstallPath/$QFETestFile.tmp
      mv $InstallPath/$QFETestFile $InstallPath/$QFETestFile.tmp
      if test $? -ne 0
      then
         echo "*** ERROR:"
         echo " Can not backup QFE infomation to $QFETestFile.tmp."
         echo ""
         return 1
      fi
   fi
      
   #==========================================================
   # Copy the updated QFE info back to .ESRI_<Product>_QFE.
   #==========================================================
   cp -p $TmpQFEFile $InstallPath/$QFETestFile
   if test $? -ne 0
   then
      echo "*** ERROR:"
      echo " Writing QFE information has failed."
      echo ""
      if [ $QFEExist -eq 1 ]
      then
         mv $InstallPath/$QFETestFile.tmp $InstallPath/$QFETestFile
         if test $? -ne 0
         then
            echo " Recover $QFETestFile was failed."
            echo ""
         fi
      fi
      rm -f $InstallPath/$QFETestFile.tmp
      return 1
   fi

   rm -f $InstallPath/$QFETestFile.tmp
   chmod 444 $InstallPath/$QFETestFile
   if test $? -ne 0
   then
      echo "*** WARNING:"
      echo " Change the $QFETestFile permission to read only failed."
      echo ""
   fi
   rm -f $InstallPath/$QFETestFileBK
   cp -p $InstallPath/$QFETestFile $InstallPath/$QFETestFileBK
   if test $? -ne 0
   then
      echo "*** WARNING:"
      echo " Backup the $QFETestFile to bin folder failed."
      echo ""
   fi

   rm -f $TmpQFEFile
   return 0
}

######################################################################
#=====================================================================
# Get_SP_Info()
#
# Get the installed service pack info form .ESRE_<Prod>_PATCH_LOG.
#=====================================================================
######################################################################
Get_SP_Info()
{
   QFEType=""
   QFETitle=0
   start=0
   FirstTime=0
   FoundSP="0"
   
   PatchFile="$InstallPath/$QFETestFile"
   if test -f $PatchFile
   then
      FindSP=`grep "QFE_TYPE: Service Pack" $PatchFile`
      if test ! -n "$FindSP"
      then
         echo 0
      else
      
         cat $PatchFile |
         ( while read file token2
         do
   
            #==========================================================
            #  If current line is blank or a comment line - skip it.
            #==========================================================
            if test ! -n "$file" -o "$file" = "#"
            then
               continue
         
            elif [ "$file" = "#START" ]
            then
               if [ $start != 0 ]
               then
                  echo "*** WARNING:"
                  echo "  #START and #END mismatch in the file $PatchFile"
               fi
               start=1
            elif [ "$file" = "#END" ]
            then
               if [ $start = 1 ]
               then
                  start=2
               else
                  echo "*** WARNING:"
                  echo "  #START and #END mismatch in the file $PatchFile"
                  echo ""
               fi
            else
               if [ $start = 1 ]
               then
                  if [ "$file" = "QFE_TYPE:" ]
                  then
                     QFEType=$token2
                  elif [ "$file" = "QFE_TITLE:" ]
                  then
                     QFETitle=$token2
                  else
                     continue
                  fi
               fi
            fi
    
            if [ $start = 2 ]
            then
               if [ "$QFEType" = "Update" ]
               then
                  echo 0
                  break
               fi
               if [ "$QFEType" = "Service Pack" -a $FirstTime -eq 0 ]
               then
                  FirstTime=1
                  echo $QFETitle
                  break
               fi
               start=0
            fi
         done )
         
         fi
   else
      echo 0
   fi
}


######################################################################
#=====================================================================
# Get_Update_Info()
#
# Get the installed Update info form .ESRE_<Prod>_PATCH_LOG.
#=====================================================================
######################################################################
Get_Update_Info()
{
   QFEType=""
   QFETitle=0
   start=0
   FirstTime=0
   FoundSP="0"
   
   PatchFile="$InstallPath/$QFETestFile"
   if test -f $PatchFile
   then
      FindSP=`grep "QFE_TYPE: Update" $PatchFile`
      if test ! -n "$FindSP"
      then
         echo 0
      else
      
         cat $PatchFile |
         ( while read file token2
         do
   
            #==========================================================
            #  If current line is blank or a comment line - skip it.
            #==========================================================
            if test ! -n "$file" -o "$file" = "#"
            then
               continue
         
            elif [ "$file" = "#START" ]
            then
               if [ $start != 0 ]
               then
                  echo "*** WARNING:"
                  echo "  #START and #END mismatch in the file $PatchFile"
               fi
               start=1
            elif [ "$file" = "#END" ]
            then
               if [ $start = 1 ]
               then
                  start=2
               else
                  echo "*** WARNING:"
                  echo "  #START and #END mismatch in the file $PatchFile"
                  echo ""
               fi
            else
               if [ $start = 1 ]
               then
                  if [ "$file" = "QFE_TYPE:" ]
                  then
                     QFEType=$token2
                  elif [ "$file" = "QFE_TITLE:" ]
                  then
                     QFETitle=$token2
                  else
                     continue
                  fi
               fi
            fi
    
            if [ $start = 2 ]
            then
               if [ "$QFEType" = "Update" -a $FirstTime -eq 0 ]
               then
                  FirstTime=1
                  echo $QFETitle
                  break
               fi
               start=0
            fi
         done )
         
         fi
   else
      echo 0
   fi
}


#=====================================================================
#  Run_Update()
#
#  Move updated Help files from $SDEHOME to $SDEHOME\..\.
#=====================================================================
######################################################################
Run_Update()
{
   if [ -d $InstallPath/Help ]
   then
     tempDir=`pwd`
     cd $InstallPath
     cp -rf Help ../.
     rm -rf Help
     cd $tempDir 
   fi
}




######################################################################
######################################################################
######################################################################
#=====================================================================
#=====================================================================
#
#                  MAIN PORTION OF PROGRAM
#
#=====================================================================
#=====================================================================
######################################################################
######################################################################
######################################################################



#================================================================
#  Initialize some variables.
#================================================================
ArcIMS=0
ArcInfo=0
ArcSDE=0
ArcGIS=0
SelectedTOC=""
ProductName=""
ProductDispName=""
ProductSerPack=""
ProductVersion=""
ProductVersionStripped=""
QFEVersion=""
QFEDate=""
QFEAbbreviated=""
ExistingProdBits=""
InstallPath=""
PatchHome=`dirname $0`
CurrentWorkingDir=`pwd`
ArcSDESet=""
ProductSetupFile="$HOME/ESRI.properties.`uname -n`"
SPNumber=0

#================================================================
#  Set platform specific system commands.
#================================================================
Set_System_Commands

#================================================================
#  Get ArcGIS product setup properties.
#================================================================
if [ -f $ProductSetupFile ]
then
   . $ProductSetupFile
fi

#================================================================
#  Print applypatch intro.
#================================================================
Print_Applypatch_Intro


#================================================================
#  Outter while loop to collect and verify selections made by the
#  user.
#================================================================
AllSetToInstall="no"
while [ $AllSetToInstall = "no" ]
do

   List_Valid_Selections

   User_Selection_Process


   #=============================================================
   #  Validate the selected QFE patch directory and contents.
   #=============================================================
   Validate_Patch_Home
   if [ $? != 0 ] 
   then
      Error_Exit
   fi

   #=============================================================
   #  Strip the decimal points from the ProductVersion.
   #=============================================================
   Strip_Product_Version
   
   Pre_Install_Info

   #==============================================================
   # Add while loop for install home path setting. If we can't auto
   # detect the current installed product bit set, prompt info to 
   # let user make sure or reset the install home path.
   #==============================================================
   HomeSetToInstall="no"
   IsFirstTimeHomeSet="yes"
   while [ $HomeSetToInstall = "no" ]
   do
      #=============================================================
      #  Determine the user's product HOME (or install location).
      #=============================================================
      Set_Product_Home

      IsFirstTimeHomeSet="no"
      
      #=============================================================
      #  Determine bitset of the user's product.
      #=============================================================
      ExistingProdBits=`Existing_Product_Bitset`

      #if [ $ArcSDE = 1 ] 
      #then
      #   AllDataBases=`Get_Patch_Info AllDataBases $CurrentTOC`
      #   AllDataBases=`Cut_String "$AllDataBases"`
      #fi

      if [ $ArcSDE = 1 ]
      then
         Validate_Selection
         if [ $? != 0 ]
         then
            exit 1
         fi
      else
         HomeSetToInstall="yes"
      fi
   done
   if [ $? != 0 ]
   then
      exit 1
   fi
   
   #=============================================================
   #  Create an update TOC file based on what the user has 
   #  installed in their product HOME.
   #  Check the final status this function containing an exit 
   #  within a loop.  For certain platforms, a call to "exit 1" 
   #  will only exit the loop and not the entire script.  This 
   #  test will catch that condition.
   #=============================================================
   Update_TOC_File
   if [ $? != 0 ]
   then
      exit 1
   fi

   #=============================================================
   #  Check to see if the directories containing the files to be
   #  installed (from UpdatedTOCFile) exist and have write 
   #  access.
   #  Check the final status this function containing an exit 
   #  within a loop.  For certain platforms, a call to "exit 1" 
   #  will only exit the loop and not the entire script.  This 
   #  test will catch that condition.
   #=============================================================
   Check_Access_Rights
   if [ $? != 0 ]
   then
      exit 1
   fi

   #=============================================================
   #  Make sure that the minimum disk space needed to install the 
   #  ESRI Patch is available.
   #=============================================================
   Check_Disk_Space

   #=============================================================
   #  Prompt the user to see if they would like to backup the 
   #  original files that will be replaced.
   #=============================================================
   Prompt_User_For_Backup

   #=============================================================
   #  Prompt the user for a backup location and verify that is 
   #  valid if the user opted to backup the original files.
   #=============================================================
   Validate_Save_Location

   #=============================================================
   #  Display the current selections made by the user and have 
   #  the user choose to confirm or change the settings.
   #  Check the final status this function containing an exit 
   #  within a loop.  For certain platforms, a call to "exit 1" 
   #  will only exit the loop and not the entire script.  This 
   #  test will catch that condition.
   #=============================================================
   Confirm_Settings
   if [ $? != 0 ]
   then
      exit 1
   fi

done


#================================================================
#  Check the final status of the call to Confirm_Settings after 
#  the outter while loop.  For certain platforms, a call to 
#  "exit 1" will only exit the loop and notthe entire script.  
#  This test will catch that condition.
#================================================================
if [ $? != 0 ]
then
   exit 1
fi

#================================================================
#  Backup the original files to the user specified location.  If 
#  there is a failure during backup, restore the originals and 
#  exit on error.
#================================================================
Perform_Backup

#================================================================
#  Walk through the Updated TOC file and remove non-writable 
#  original files.
#
#  We know we have full access rights to the directories but some 
#  of the original files to be replaced may be "read only" or 
#  root-owned with the "set-user-id" bit set.  These cannot be 
#  updated by the tar command unless the old version is first
#  removed, so remove them now.
#================================================================
Remove_NonWritable_Files


Apply_The_Patch

Verify_The_Install

Run_Update

Clean_Up
exit 0
